これは、なにをしたくて書いたもの?
Sonatype Nexus 3のDockerレジストリーを使って匿名ユーザーからのDockerイメージのpullができるようにしようと思ったのですが、
これにかなりハマったのでメモしておきます。
なんで困ったのか?
Docker Hubのプロキシレジストリーを作った時に、Docker HubのDockerイメージを取得するくらいは匿名ユーザーでのpullを
許可してもいいと思ったのですが、これをやろうとしてハマったので。
環境
Sonatype Nexus 3.82.0-08を使っているものとします。
また動作確認にDockerと
$ 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
Terraformを使った環境構築を行います。
$ terraform version Terraform v1.12.2 on linux_amd64
条件
匿名ユーザーでDockerイメージのpullができる条件を書いていきます。
ひとまず、匿名ユーザーでのアクセス自体は許可されている必要があります。「Allow anonymous users to access the server」に
チェックが入っていること、ですね。

そして、Reamlsで「Docker Bearer Token Realm」がアクティブになっていることです。
デフォルトでは入っていないので

こうして「Save」します。

anonymousユーザーの権限はデフォルトで問題なく、

あとはDockerレジストリーを作成する時に「Allow anonymous docker pull」にチェックを入れておきます。

よく見ると
Allow anonymous docker pull ( Docker Bearer Token Realm required )
と書いてあるのですが、すぐに気づきません…。
確認する
では、実際に確認してみましょう。
Terraformの構成ファイル。
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 = true 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 } }
ポイントはここで、Realmsに「DockerToken」を入れていることですね。
resource "nexus_security_realms" "this" { active = [ "NexusAuthenticatingRealm", "DockerToken", ] }
この名前はRealmsのページに書いてあります。
今回のDockerレジストリーは、Hosted、Proxy(Docker Hubプロキシ)、Groupの3つですが、Hostedのみpullに認証を
必須にしました。Groupレジストリー越しにHostedレジストリーにあるDockerイメージをpullした場合にどうなるかは
確認してみます。
リソース作成。
$ terraform init $ terraform apply
確認してみましょう。
Dockerデーモンにinsecure-registriesの設定をして
/etc/docker/daemon.json
{ "insecure-registries": [ "192.168.33.11:5000", "192.168.33.11:15000" ] }
再起動。
$ sudo systemctl restart docker
Dockerイメージをpull。
$ docker image pull 192.168.33.11:15000/nginx:1.29.0-bookworm
成功しました。
$ 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 image tag 192.168.33.11:15000/nginx:1.29.0-bookworm 192.168.33.11:5000/nginx:1.29.0-bookworm
Hostedレジストリーにログインしてからpush。
$ 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 $ docker image push 192.168.33.11:5000/nginx:1.29.0-bookworm
Dockerイメージを削除。
$ docker image rm 192.168.33.11:5000/nginx:1.29.0-bookworm Untagged: 192.168.33.11:5000/nginx:1.29.0-bookworm Untagged: 192.168.33.11:5000/nginx@sha256:3651f5785567a226fd58e33adcfb27b41a83ba0c3649d9ee9ac590acd97bad51
ログアウト。
$ docker logout 192.168.33.11:5000 Removing login credentials for 192.168.33.11:5000
pullすると、こちらは失敗します。
$ docker image pull 192.168.33.11:5000/nginx:1.29.0-bookworm Error response from daemon: Head "http://192.168.33.11:5000/v2/nginx/manifests/1.29.0-bookworm": no basic auth credentials
ログイン後なら、pullできるようになります。
$ docker login 192.168.33.11:5000 $ docker image pull 192.168.33.11:5000/nginx:1.29.0-bookworm
今度は、もっとわかりやすく名前を付け替えてみましょうか。
$ docker image pull 192.168.33.11:15000/nginx:1.29.0-bookworm $ docker image tag 192.168.33.11:15000/nginx:1.29.0-bookworm 192.168.33.11:5000/my-nginx:latest $ docker image push 192.168.33.11:5000/my-nginx:latest
1度Dockerイメージを削除。
$ docker image rm 192.168.33.11:15000/nginx:1.29.0-bookworm 192.168.33.11:5000/my-nginx:latest
Hostedレジストリーからログアウトしてから
$ docker logout 192.168.33.11:5000 Removing login credentials for 192.168.33.11:5000
Hostedレジストリーからpullしてみます。
$ docker image pull 192.168.33.11:5000/my-nginx:latest Error response from daemon: Head "http://192.168.33.11:5000/v2/my-nginx/manifests/latest": no basic auth credentials
ログインした後であればうまくいきます。
$ docker login 192.168.33.11:5000 $ docker image pull 192.168.33.11:5000/my-nginx:latest
Groupレジストリーからはどうでしょう?
$ docker image pull 192.168.33.11:15000/my-nginx:latest
こちらはログインしていなくてもpullできるようです。
というわけで、HostedレジストリーにあるDockerイメージをpullする際に認証必須としたい場合は、匿名アクセスが可能な
Groupレジストリーに含めるのをやめるか、Groupレジストリーを認証必須にするかという感じですね。
おわりに
Sontype Nexus 3のDockerレジストリーで、匿名ユーザーからのDockerイメージのpullを許可する方法を調べてみました。
「Docker Bearer Token Realm」の存在になかなか気づかなかったので、かなり苦労しました。
ただ、設定としてはやりたくなる気がするので覚えておいた方がよいかな、と。