これは、なにをしたくて書いたもの?
Dockerデーモンの設定に、Docker Hubのミラーが設定できることを知ったので、Sonatype NexusでDockerレジストリーを
作成して使ってみることにしました。
Docker Hubのミラーを設定する
Docker Hubのミラー設定に関するドキュメントはこちら。
このページでは次の2つの設定が書かれています。
- ローカルにDockerレジストリーを導入し、Docker Hubへのpull-throughキャッシュとして設定する
- Dockerデーモンにミラーの設定を行う
今回はDockerレジストリーとしてSonatype Nexusを使い、Docker Hubのミラーとして設定してみます。
Sonatype Nexusでは、Docker Hubへのプロキシリポジトリーを含むものとします。
環境
今回は次の2つのサーバーで確認を行います。
flowchart LR subgraph Host1/192.168.33.10 A["docker"] end subgraph Host2/192.168.33.11 A -- "HTTP" --> B["Sonatype Nexus"] end
192.168.33.10のサーバーのDocker。
$ vagrant ssh -c bash [fog][WARNING] Unrecognized arguments: libvirt_ip_command vagrant@host1:~$ docker version Client: Docker Engine - Community Version: 28.3.3 API version: 1.51 Go version: go1.24.5 Git commit: 980b856 Built: Fri Jul 25 11:34:09 2025 OS/Arch: linux/amd64 Context: default Server: Docker Engine - Community Engine: Version: 28.3.3 API version: 1.51 (minimum version 1.24) Go version: go1.24.5 Git commit: bea959c Built: Fri Jul 25 11:34:09 2025 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.7.27 GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da runc: Version: 1.2.5 GitCommit: v1.2.5-0-g59923ef docker-init: Version: 0.19.0 GitCommit: de40ad0
192.168.33.11ではSonatype Nexus 3.82.0-08が稼働しているものとします。
Dockerレジストリーの作成は、Terraformで行うことにします。
$ terraform version Terraform v1.12.2 on linux_amd64
Sonatype NexusにDockerレジストリーを作成する
まずはSonatype NexusにDockerレジストリーを作成しましょう。
main.tf
terraform { required_version = "v1.12.2" required_providers { nexus = { source = "datadrivers/nexus" version = "2.6.0" } } } provider "nexus" { username = "admin" password = "admin123" url = "http://192.168.33.11:8081" insecure = true } resource "nexus_security_realms" "this" { active = [ "NexusAuthenticatingRealm", "DockerToken", ] } resource "nexus_repository_docker_proxy" "dockerhub" { name = "docker-dockerhub-proxy" online = true docker { force_basic_auth = false v1_enabled = false } docker_proxy { index_type = "HUB" } storage { blob_store_name = "default" strict_content_type_validation = true } proxy { remote_url = "https://registry-1.docker.io" content_max_age = 1440 metadata_max_age = 1440 } negative_cache { enabled = true ttl = 1440 } http_client { blocked = false auto_block = true } } resource "nexus_repository_docker_hosted" "this" { name = "docker-hosted" online = true docker { force_basic_auth = false http_port = 5000 v1_enabled = false } storage { blob_store_name = "default" strict_content_type_validation = true write_policy = "ALLOW" } } resource "nexus_repository_docker_group" "group" { name = "docker-group" online = true docker { force_basic_auth = false http_port = 15000 v1_enabled = false } group { member_names = [ nexus_repository_docker_hosted.this.name, nexus_repository_docker_proxy.dockerhub.name, ] } storage { blob_store_name = "default" strict_content_type_validation = true } }
Dockerクライアントから直接アクセスするDockerレジストリーには、ポートを割り当てています。
docker { force_basic_auth = true http_port = 5000 v1_enabled = false } docker { force_basic_auth = true http_port = 15000 v1_enabled = false }
これを指定しない場合、Sonatype Nexusがリッスンしているポートを使うのですが、アクセスする時のパスに
Dockerレジストリー名が入ってしまいます。これはDockerクライアントからは受け入れられないので、代わりに専用の
ポートを指定することになります。
Docker Registry / Port Connectors
あと、force_basic_auth
をfalse
にしておいて匿名アクセスを有効にしているのですが、以下がないと未ログインでのpullが
うまくいかず、とてもハマりました…。
resource "nexus_security_realms" "this" { active = [ "NexusAuthenticatingRealm", "DockerToken", ] }
では、リソースを作成。
$ terraform init $ terraform apply
Dockerクライアントから使う
では、Dockerクライアントから使ってみましょう。
HTTPでアクセスするので、insecure-registries
に登録しておきます。
/etc/docker/daemon.json
{ "insecure-registries": [ "192.168.33.11:5000", "192.168.33.11:15000" ] }
Dockerデーモンを再起動。
$ sudo systemctl restart docker
未ログインでDockerイメージをpullしてみます。
$ docker image pull 192.168.33.11:15000/nginx:1.29.0-bookworm
OKですね。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.33.11:15000/nginx 1.29.0-bookworm 2cd1d97f893f 2 weeks ago 192MB
Docker Hostedレジストリーにログイン。
$ docker login 192.168.33.11:5000 Username: admin Password: WARNING! Your credentials are stored unencrypted in '/home/vagrant/.docker/config.json'. Configure a credential helper to remove this warning. See https://docs.docker.com/go/credential-store/ Login Succeeded
先ほどpullしたDockerイメージのタグをつけ直します。
$ docker image tag 192.168.33.11:15000/nginx:1.29.0-bookworm 192.168.33.11:5000/nginx:1.29.0-bookworm
push。こちらはログイン必須です。
$ docker image push 192.168.33.11:5000/nginx:1.29.0-bookworm
うまくいきました。
The push refers to repository [192.168.33.11:5000/nginx] f17478b6e8f3: Pushed 0662742b23b2: Pushed 5c91a024d899: Pushed 6b1b97dc9285: Pushed a6b19c3d00b1: Pushed 30837a0774b9: Pushed 7cc7fe68eff6: Pushed 1.29.0-bookworm: digest: sha256:3651f5785567a226fd58e33adcfb27b41a83ba0c3649d9ee9ac590acd97bad51 size: 1778
Docker GroupレジストリーをDocker Hubのミラーとして使う
次は今回のお題です。Docker GroupレジストリーをDocker Hubのミラーとして使ってみましょう。
daemon.json
ファイルにregistry-mirrors
を追加し、Docker GroupレジストリーのURLを追加します。
/etc/docker/daemon.json
{ "insecure-registries": [ "192.168.33.11:5000", "192.168.33.11:15000" ], "registry-mirrors": [ "http://192.168.33.11:15000" ] }
Dockerデーモンを再起動。
$ sudo systemctl restart docker
ApacheのDockerイメージを、Docker Hubからpullしてみます。
$ docker image pull httpd:2.4.65-bookworm
この時、Sonatype Nexusのログを確認してみます。
$ tail -f sonatype-work/nexus3/log/request.log
すると、最初のリクエストは未ログインとなっているものの、その後にanonymousユーザーでDockerイメージのpullが
できていることがわかります。
192.168.33.10 - - [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/ HTTP/1.1" 401 - 113 11 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-20] 192.168.33.10 - - [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/token?scope=repository%3Alibrary%2Fhttpd%3Apull&service=http%3A%2F%2F192.168.33.11%3A15000%2Fv2%2Ftoken HTTP/1.1" 200 - 60 11 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-148] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "HEAD /repository/docker-group/v2/library/httpd/manifests/2.4.65-bookworm HTTP/1.1" 200 - 0 23 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-88] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/manifests/sha256:fbc12199ccad031d8047e9c789d65aceee2d14f99ba90664cd3a3996867a5582 HTTP/1.1" 200 - 10160 27 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-145] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/manifests/sha256:cc4c94eb4e9c3d94ac2147cb9ce8057096362de83fa12b7aeecd4c0c3d5d1f21 HTTP/1.1" 200 - 2095 21 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-20] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/blobs/sha256:5bdbc621ec089f8137cf0fdd49caa16748854c8c72739e794d1c2c9ab88dfed7 HTTP/1.1" 200 - 7883 33 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-147] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/blobs/sha256:c02ce4e0ebb3594adf5979faef0f7a23c3ec1a1e8810d6395dc92927064550e0 HTTP/1.1" 200 - 146 33 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-20] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/blobs/sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1 HTTP/1.1" 200 - 32 38 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-160] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/blobs/sha256:fc61fad0f5407d576719977190667f34c33556d8e7b9a57acf4407d93e822e9b HTTP/1.1" 200 - 4208310 50 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-88] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/blobs/sha256:644bfd3d7e686c06dc8c06f517c9aafd1e06867545b3b6d8737ff3a492ed9fb7 HTTP/1.1" 200 - 295 49 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-20] 192.168.33.10 - anonymous [02/Aug/2025:10:54:52 +0000] "GET /repository/docker-group/v2/library/httpd/blobs/sha256:e7b83145b2097d99a6c7a096934f9ef9f7b6f2818863e20c2652b05f42c1bcb4 HTTP/1.1" 200 - 26067888 79 "docker/28.3.3 go/go1.24.5 git-commit/bea959c kernel/6.8.0-71-generic os/linux arch/amd64 UpstreamClient(Docker-Client/28.3.3 \\(linux\\))" [qtp1529159609-150]
OKですね。
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE httpd 2.4.65-bookworm 5bdbc621ec08 9 days ago 148MB 192.168.33.11:15000/nginx 1.29.0-bookworm 2cd1d97f893f 2 weeks ago 192MB 192.168.33.11:5000/nginx 1.29.0-bookworm 2cd1d97f893f 2 weeks ago 192MB
おわりに
Sonatype Nexus 3で作成したDockerレジストリーを、Docker Hubのミラーとして使ってみました。
ミラーという機能自体を知らなかったので、いい機会になりましたね。
Sonatype NexusのDockerレジストリーでの匿名アクセスについてはだいぶハマったので、別エントリーでメモしておこうと
思います…。