認証と SSL を備えた nginx リバース プロキシの背後にある docker レジストリ

認証と SSL を備えた nginx リバース プロキシの背後にある docker レジストリ

プライベート Docker レジストリにリモートでイメージをプッシュしようとしていますが、次のように失敗します。

$ podman push sub.example.com:5000/dummyimg sub.example.com:5000/rem/dummyimg
Getting image source signatures
Copying blob 0fbe8c68abd3 done
Copying blob 30085473d084 done
Copying blob 664eb87278f9 done
Copying blob c8db7b4be633 done
Copying blob f1417ff83b31 [=====================>----------------] 4.0MiB / 7.0MiB
Copying blob d007f013021f [===========================>----------] 4.0MiB / 5.4MiB
Error: writing blob: Patch "index404.html": stopped after 10 redirects

ログには次のようなエラーが表示されます。

time="2023...Z" level=error msg="response completed with error" err.code="blob unknown"
err.detail=sha256:0fbe...04 err.message="blob unknown to registry" go.version=go1.16.15 
http.request.host=sub.example.com http.request.id=440cfc9f-272d-493a-be95-c6f29bfae3dd 
http.request.method=HEAD http.request.remoteaddr=1.2.3.4 
http.request.uri="/v2/rem/dummyimg/blobs/sha256:0fbe...04" 
http.request.useragent="containers/5.16.0 (github.com/containers/image)" 
http.response.contenttype="application/json; charset=utf-8" 
http.response.duration=4.959982ms http.response.status=404 http.response.written=157 
vars.digest="sha256:0fbe...04" vars.name="rem/dummyimg"

sub.example.com:5000に正常にログインできます

$ podman login sub.example.com:5000
Username: testuser
Password: 
Login Succeeded!

curl経由でカタログを照会できる

$ curl -u testuser https://sub.example.com:5000/v2/_catalog

私は、nginx プロキシ経由で SSL を使用した基本認証を使用してレジストリにアクセスします。以下は基本的に、docker レジストリのドキュメントで指示されていること + デフォルトのサーバー構成、nginx 構成です。

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name _;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        server_name _;

        root /var/www/html;

        ssl_certificate "/etc/letsencrypt/live/example.com/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/example.com/privkey.pem";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout 10m;

        index index404.html;
        error_page 404 index404.html;

        location / {
                try_files $uri $uri/ =404;
        }
}

server {
        listen 443 ssl http2;
        server_name example.com www.example.com;

        ssl_certificate "/etc/letsencrypt/live/example.com/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/example.com/privkey.pem";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout 10m;

        location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://localhost:8080;
        }
}

# for podman registry
map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
        '' 'registry/2.0';
}

server {
        listen 5000 ssl http2;
        server_name sub.example.com;

        ssl_certificate "/etc/letsencrypt/live/example.com/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/example.com/privkey.pem";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout 10m;

        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_prefer_server_ciphers on;

        client_max_body_size 16384m;
        chunked_transfer_encoding on;

        location / {
                add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;

                auth_basic "Registry realm";
                auth_basic_user_file /var/www/_auth/htpass2;

                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto "https";
                proxy_pass http://127.0.0.1:5001;
        }
}

SSL証明書にはexample.comやsub.example.comを含むすべての名前が含まれます

レジストリのコンテナは次のように作成されます。

#!/bin/bash
BASE=/home/some/folder

podman create -p 127.0.0.1:5001:5000 \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
-v $BASE/registry:/var/lib/registry \
--replace \
--name myregistry \
registry:2

次に、単純に実行します:

$ podman run myregistry

長文であることは承知していますが、助けてください :)、プロキシなしでサーバーにローカルに画像をプッシュできますが、SSL と基本認証を使用してリモートでレジストリにプッシュできるようにしたいと考えています。

関連情報