在 nginx 代理后面使用 docker 私有注册表 (v2) 的 HTTP 响应格式错误

Posted

技术标签:

【中文标题】在 nginx 代理后面使用 docker 私有注册表 (v2) 的 HTTP 响应格式错误【英文标题】:malformed HTTP response with docker private registry (v2) behind an nginx proxy 【发布时间】:2015-10-14 11:35:41 【问题描述】:

我已经按照他们的官方文档在 CentOS 7 机器上设置了一个 Docker 私有注册表 (v2):https://docs.docker.com/registry/deploying/

我在 Fedora 21 机器上运行 docker 1.6.0。

注册表在端口 5000 上运行,并使用由受信任的 CA 签名的 SSL 密钥。我将“docker-registry.example.com”的 DNS 记录设置为服务器的内部 IP。运行“docker pull docker-registry.example.com:5000/tag/image”,它按预期工作。

我设置了一个 nginx 服务器,运行 nginx 版本:nginx/1.8.0,并为 'nginx-proxy.example.com' 设置了一个指向 nginx 服务器的 dns 记录,并设置了一个站点。这是配置:

server 
   listen 443 ssl;
   server_name nginx-proxy.example.com;

   add_header Docker-Distribution-Api-Version: registry/2.0 always;

   ssl on;
   ssl_certificate /etc/ssl/certs/cert.crt;
   ssl_certificate_key /etc/ssl/certs/key.key;

   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-Proto $scheme;
   proxy_set_header X-Original-URI $request_uri;
   proxy_set_header Docker-Distribution-Api-Version registry/2.0;

   location / 
     proxy_pass http://docker-registry.example.com:5000;
   

当我尝试运行“docker pull nginx-proxy.example.com/tag/image”时,出现以下错误:

FATA[0001] Error response from daemon: v1 ping attempt failed with error: Get https://nginx-proxy.example.com/v1/_ping: malformed HTTP response "\x15\x03\x01\x00\x02\x02"

我的问题是双重的。

    为什么 docker 客户端要查找 /v1_/ping? 为什么我看到“格式错误的 http 响应”

如果我运行 'curl -v nginx-proxy.example.com/v2' 我会看到:

[root@alex amerenda] $ curl -v https://nginx-proxy.example.com/v2/
* Hostname was NOT found in DNS cache
*   Trying 10.1.43.165...
* Connected to nginx-proxy.example.com (10.1.43.165) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*   subject: CN=*.example.com,O="example, Inc.",L=New York,ST=New York,C=US
*   start date: Sep 15 00:00:00 2014 GMT
*   expire date: Sep 15 23:59:59 2015 GMT
*   common name: *.example.com
*   issuer: CN=GeoTrust SSL CA - G2,O=GeoTrust Inc.,C=US
> GET /v2/ HTTP/1.1
> User-Agent: curl/7.37.0
> Host: nginx-proxy.example.com
> Accept: */*
> \x15\x03\x01\x00\x02\x02

如果我执行“curl -v docker-registry.example.com”,我会得到 200 OK 响应。所以nginx必须对此负责。有谁知道为什么会这样?快把我逼疯了!

【问题讨论】:

【参考方案1】:
 proxy_pass http://docker-registry.example.com:5000;

您正在使用纯 HTTP(即没有 https)传递请求

\x15\x03\x01\x00\x02\x02

您将收到 SSL 响应。所以看起来你必须使用 https:// 而不是 http:// 来访问端口 5000。你甚至知道你正在使用 SSL:

注册表在端口 5000 上运行,并且正在使用由受信任的 CA 签名的 SSL 密钥...

除此之外:请使用为 example.com 等示例保留的名称,并且不要在示例中使用不属于您的域名。

【讨论】:

谢谢!做到了。我知道这很明显......另外,我将“domain.com”的实例更改为“example.com” 有趣,@Steffen!您是如何意识到响应是 SSL 的? @fex: 因为 \x15\x03\x01 是 TLS 警报的开始,即 TLS 记录层类型警报 (\x15) 后跟 TLS 协议版本主要和次要 - \x03\x01 是TLS 1.0。服务器在 TLS 中抱怨 - 这意味着它需要 TLS 而不是纯 HTTP:

以上是关于在 nginx 代理后面使用 docker 私有注册表 (v2) 的 HTTP 响应格式错误的主要内容,如果未能解决你的问题,请参考以下文章

带有ssl的nginx代理后面的docker容器内的Wordpress

在 Nginx 代理后面时,Keycloak Docker Instace 中的 X-Frame-Options 拒绝加载

在 Nginx 后面运行 Docker Engine API

Docker Nginx 反向代理

为Docker创建自动化nginx反向代理

使用Harbor搭建企业级私有docker仓库