CLOVER🍀

That was when it all began.

Sontype Nexus 3のDockerレジストリーで、匿名ユーザーからのDockerイメージのpullを許可する

これは、なにをしたくて書いたもの?

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」に
チェックが入っていること、ですね。

Anonymous Access

そして、Reamlsで「Docker Bearer Token Realm」がアクティブになっていることです。

デフォルトでは入っていないので

こうして「Save」します。

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

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

Docker Authentication

よく見ると

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のページに書いてあります。

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」の存在になかなか気づかなかったので、かなり苦労しました。

ただ、設定としてはやりたくなる気がするので覚えておいた方がよいかな、と。