如何登录设置了HTTP前缀的Docker注册表?

Rus*_*our 5 docker docker-registry

我已经设置了自己的Docker注册表,但是我不想在根URL上使用它,因此在创建服务时,我使用了REGISTRY_HTTP_PREFIX环境变量并将其设置为/registry/,因此注册表的URL为https://tools.example.com/registry。Nginx已对此进行代理,后者具有基本身份验证设置。

我使用浏览器测试了对注册表的访问,并能够通过以下步骤获取它来表明没有存储库http://tools.example.com/registry/v2/_catalog:

在此处输入图片说明

这使我认为这是行之有效的。但是,当我尝试使用Docker命令行登录到注册表时,遇到基本身份验证挑战,但是由于URL不正确而导致登录失败,例如

docker login -u russells -p xxxxxxxx https://tools.example.com/registry/
Error response from daemon: login attempt to https://tools.example.com/v2/ failed with status: 404 Not Found
Run Code Online (Sandbox Code Playgroud)

从错误中可以看出,前缀未正确添加。因此,我该如何登录注册表,以便推送图像。是否存在环境变量或我缺少的一些东西才能docker login正常工作?

更新-2017-08-12 2253 BST

我一直在研究配置,但是我仍未走得太远。

根据要求,这里是我的配置文件。

nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    keepalive_timeout  65;

    upstream docker-registry {
        server registry:5000;
    }

    map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
        '' 'registry/2.0';
    }

    server {
        listen 15000;
        server_name tools.example.com;

        # disable any limits to avoid HTTP 413 for large image uploads
        client_max_body_size 0;

        # required to avoid HTTP 411
        chunked_transfer_encoding on;

        location /registry/ {

            # Do not allow connections from docker 1.5. and earlier
            # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
            if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$") {
                return 404;
            }

            auth_basic "Docker Registry";
            auth_basic_user_file /etc/nginx/.htpasswd;

            add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;

            proxy_pass                      http://docker-registry/registry/;
            proxy_set_header    Host        $http_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 $scheme;
            proxy_read_timeout              900;

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的Docker Registry Service部署为registry并在默认端口5000上运行。现在看来,我感到有些困惑。我不需要注册表来回答前缀本身,只需Nginx。

例如,如果我将位置设置为,/则可以登录,但是如果将其更改为,/registry/则无法登录。我开始认为两者是相互冲突的。

登记处

除了一个环境变量-之外REGISTRY_HTTP_PREFIX,我没有为注册表设置任何配置,这可能超出了此设置中的要求。

更新-2017-08-15 1100 BST

为了测试prefix注册表,我使用以下配置文件创建了一个注册表容器:

version: 0.1
auth:
  htpasswd:
    realm: Docker Registry
    path: /auth/etc/htpasswd
storage:
  filesystem:
    rootdirectory: /var/lib/registry
    maxthreads: 100
http:
  addr: 0.0.0.0:5000
  prefix: /registry/
  tls:
    certificate: /auth/ssl/certs/registry.cert
    key: /auth/ssl/private/registry.key
Run Code Online (Sandbox Code Playgroud)

因为这是使用自签名证书,所以我通过将证书放在中来更新了Docker引擎/etc/docker/certs.d/host-lin-01:5000。

然后,我使用以下命令创建了容器:

docker run -it --rm -p 5000:5000 --name registry_test -v ~/workspaces/docker/registry/etc/registry.yml:/etc/docker/registry/config.yml -v ~/workspaces/docker/registry:/auth registry:2

如果我尝试使用以下命令登录到注册表:

docker login -u russells -p xxxxxx https://host-lin-01:5000/registry

我收到以下错误:

Error response from daemon: login attempt to https://host-lin-01:5000/v2/ failed with status: 404 Not Found

现在,如果我perfix: /registry/从注册表yaml文件中删除该行并重新启动容器,然后登录,一切正常:

docker login -u russells -p xxxxxx https://turtle-host-03:5000/
Login Succeeded
Run Code Online (Sandbox Code Playgroud)

但是,奇怪的是,该登录名适用于我在登录URL末尾添加的任何前缀,例如

docker login -u russells -p xxxxxx https://turtle-host-03:5000/registry/fred/34
Login Succeeded
Run Code Online (Sandbox Code Playgroud)

我不明白这个。我一定误会了prefix设置的作用。

Tar*_*ani 0

您发出的是您的基本身份验证的应用程序。因此,您拥有带有基本身份验证的 Nginx,它由普通注册表支持。

您可以验证 url 并查看 _catalog 空白 json,这让您感觉它正在工作。但从技术上讲,发生的情况是你的 Nginx 要求输入用户名/密码,它获取它然后将其传递到你的 docker 注册表。而这又没有身份验证。

现在,当您使用时,docker login您期望获得经过身份验证的注册表,但您拥有经过身份验证的 nginx 和未经身份验证的注册表。所以你需要从 nginx 配置中删除以下代码行

auth_basic "Docker Registry";
auth_basic_user_file /etc/nginx/.htpasswd;
Run Code Online (Sandbox Code Playgroud)

此外,在启动注册表时,您需要定义以下环境变量

  REGISTRY_AUTH: htpasswd
  REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
  REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
Run Code Online (Sandbox Code Playgroud)

确保/auth/htpasswd从主机映射到注册表容器。执行此操作,设置应该可以工作。另请确保在 docker 客户端系统中设置服务器证书

可选更改

这个答案的下一部分是可选的。由于您同时使用 Nginx 和Registry。我建议您REGISTRY_HTTP_PREFIX从注册表中删除 并将其更改proxy_pass为

proxy_pass http://docker-registry/;
Run Code Online (Sandbox Code Playgroud)