使用Nginx验证代理
预计阅读时间:5分钟
该页面包含有关使用开源Docker Registry托管自己的注册表的信息。有关Docker Hub的信息,它提供了托管注册表以及其他功能,例如团队,组织,Web挂钩,自动构建等,请参阅Docker Hub。
用例
人们已经依靠nginx代理对他们的用户进行其他服务的身份验证了,他们可能想利用它,并通过同一管道来传输注册表通信。
通常,这包括在后端使用LDAP / AD的企业设置以及在其内部http门户前面的SSO机制。
备择方案
如果您只想对您的注册表进行身份验证,并且愿意单独维护用户访问权限,则应该考虑使用本机 基本身份验证注册表功能。
解决方案
使用此处介绍的方法,您可以在注册表前面的反向代理中为docker引擎实现基本身份验证。
虽然我们以一个简单的htpasswd文件为例,但是在完成该示例后,任何其他nginx身份验证后端都应该非常容易实现。
为了示例,我们还实现了对受限用户组的推送限制。同样,您应该修改此设置以适合您的里程。
陷阱
虽然此模型使您能够通过代理内部实现的辅助身份验证机制使用所需的任何身份验证后端,但它还需要将TLS终止从注册表移到代理本身。
注意:Docker不建议您在
localhost:5000
未经身份验证的情况下将您的注册表绑定到。这会在您的Docker Registry安全性中造成潜在的漏洞。因此,任何可以登录运行Docker Registry的服务器的用户都可以在不进行身份验证的情况下推送映像。
此外,在通信管道中引入额外的http层会使部署,维护和调试更加复杂。确保需要额外的复杂性。
例如,处于HTTPS模式的Amazon的Elastic Load Balancer(ELB)已经设置了以下客户端标头:
X-Real-IP
X-Forwarded-For
X-Forwarded-Proto
因此,如果您后面有一个Nginx实例,请从下面的示例配置中删除这些行:
proxy_set_header Host $http_host; # required for docker client's sake
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
否则,Nginx会重置ELB的值,并且无法正确路由请求。有关更多信息,请参见 #970。
设置东西
查看要求,然后执行以下步骤。
-
创建所需的目录
mkdir -p auth data
-
创建主要的nginx配置。将此代码块粘贴到名为的新文件中
auth/nginx.conf
:events { worker_connections 1024; } http { upstream docker-registry { server registry:5000; } ## Set a variable to help us decide if we need to add the ## 'Docker-Distribution-Api-Version' header. ## The registry always sets this header. ## In the case of nginx performing auth, the header is unset ## since nginx is auth-ing before proxying. map $upstream_http_docker_distribution_api_version $docker_distribution_api_version { '' 'registry/2.0'; } server { listen 443 ssl; server_name myregistrydomain.com; # SSL ssl_certificate /etc/nginx/conf.d/domain.crt; ssl_certificate_key /etc/nginx/conf.d/domain.key; # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; # disable any limits to avoid HTTP 413 for large image uploads client_max_body_size 0; # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486) chunked_transfer_encoding on; location /v2/ { # 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; } # To add basic authentication to v2 use auth_basic setting. auth_basic "Registry realm"; auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd; ## If $docker_distribution_api_version is empty, the header is not added. ## See the map directive above where this variable is defined. add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always; proxy_pass http://docker-registry; proxy_set_header Host $http_host; # required for docker client's sake proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 900; } } }
-
auth/nginx.htpasswd
为“ testuser”和“ testpassword”创建一个密码文件。$ docker run --rm --entrypoint htpasswd registry:2 -Bbn testuser testpassword > auth/nginx.htpasswd
注意:如果不想使用
bcrypt
,则可以省略该-B
参数。 -
将您的证书文件复制到
auth/
目录中。$ cp domain.crt auth $ cp domain.key auth
-
创建撰写文件。将以下YAML粘贴到名为的新文件中
docker-compose.yml
。nginx: # Note : Only nginx:alpine supports bcrypt. # If you don't need to use bcrypt, you can use a different tag. # Ref. https://github.com/nginxinc/docker-nginx/issues/29 image: "nginx:alpine" ports: - 5043:443 links: - registry:registry volumes: - ./auth:/etc/nginx/conf.d - ./auth/nginx.conf:/etc/nginx/nginx.conf:ro registry: image: registry:2 volumes: - ./data:/var/lib/registry
开始和停止
现在,开始堆栈:
docker-compose up -d
使用“推送”授权用户登录(使用testuser
和testpassword
),然后标记并推送您的第一张图片:
docker login -u=testuser -p=testpassword -e=root@example.ch myregistrydomain.com:5043
docker tag ubuntu myregistrydomain.com:5043/test
docker push myregistrydomain.com:5043/test
docker pull myregistrydomain.com:5043/test