| tags: [ Docker ] categories: [ Development ]
给阿里云容器镜像服务器架设反向代理
早期我司使用 Harbor 自建 Docker Registry,后来阿里云推出了容器镜像服务,服务还处于公测阶段,使用免费,看起来不错,但是两者的 URI 是不一样的:
- 我司:registry.example.com/NAMESPACE/REPOSITORY
- 阿里云:registry.cn-shenzhen.aliyuncs.com/PREFIX_NAMESPACE/REPOSITORY
除了域名不一样,两者的 namespace 也不一样,阿里云比较矬,它的 RDS、Redis 服务提供的域名是每个用户不一样的,而 docker registry 却选择了一个固定域名,于是不同租户的 namespace 名字会冲突,非常不幸的是我司用的 namespace 名字已经被人占用了,阿里云推荐的解决办法是加一个公司名字前缀。 由于这个原因,我们不能把 registry.example.com以 DNS CNAME 的方式直接映射到 registry.cn-shenzhen.aliyuncs.com,而是要借助一层 Nginx 代理:
http {
map $args $mapped_args {
# 在认证时把 NAMESPACE/REPOS 映射到 PREFIX_NAMESPACE/REPOS
~(.*)scope=repository%3A(.*) $1scope=repository%3APREFIX_$2;
default $args;
}
server {
listen 443 ssl;
server_name registry.example.com;
tcp_nodelay on;
# this is necessary for us to be able to disable request buffering in all cases
proxy_http_version 1.1;
# SSL
ssl_certificate cert/registry.example.com.pem;
ssl_certificate_key cert/registry.example.com.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/docker/docker/issues/1486)
chunked_transfer_encoding on;
proxy_buffering off;
proxy_request_buffering off;
# 拦截服务端返回的认证服务器地址
location = /v2/ {
# 更理想的是替换服务端返回的 http reader,但 Nginx 标准模块没这个功能,所幸 service 参数貌似是固定的
add_header Www-Authenticate 'Bearer realm="https://registry.example.com/auth",service="registry.aliyuncs.com:cn-shenzhen:26842"' always;
proxy_pass https://registry.cn-shenzhen.aliyuncs.com/v2/;
# 丢掉服务端返回的 Www-Authenticate 头部
proxy_hide_header Www-Authenticate;
}
# 改写 NAMESPACE/REPOS 为实际的 PREFIX_NAMESPACE/REPOS 以获取 access token
location /auth {
#rewrite_log on;
set $args $mapped_args;
rewrite ^(.*)$ $1 break;
proxy_pass https://dockerauth.cn-hangzhou.aliyuncs.com;
}
# 将 /v2/NAMESPACE/... 重写成 /v2/PREFIX_NAMESPACE/...
location /v2/ {
#rewrite_log on;
rewrite ^/v2/(?:PREFIX_)?(.+) /v2/PREFIX_$1 break;
proxy_pass https://registry.cn-shenzhen.aliyuncs.com;
}
}
}
这个 hack 的起因虽然是针对阿里云容器镜像服务,但应该是通用的,Docker registry 的网络协议是由 Docker 官方明文规定的,只要是想改变 docker image 的 NAMESPACE 部分,都可以用上面的办法代理转换一把。