推送至安全Docker Registry遇400错误:HTTP请求发至HTTPS端口
问题分析与解决方法
你遇到的400 Bad Request: The plain HTTP request was sent to HTTPS port错误,核心是Docker客户端在推送镜像时,部分请求(比如日志里的PATCH请求)没有走HTTPS协议,或者证书配置路径有误,导致客户端尝试用HTTP连接HTTPS端口被Nginx拦截。下面是具体原因和解决步骤:
可能的原因及对应修复方案
1. Docker客户端证书目录命名错误
你提到把证书存在C:\ProgramData\Docker\certs.d\hostName8080\ca.crt,这里的目录名不符合Docker的规则——证书目录必须严格按照<registry-host>:<port>的格式命名,正确路径应该是:
C:\ProgramData\Docker\certs.d\hostName:8080\ca.crt
修复步骤:
- 把文件夹重命名为
hostName:8080(主机名和端口用冒号分隔) - 重启Docker服务,让配置生效
2. Nginx代理未正确支持Docker Registry的PATCH请求
默认的centurylinklabs/nginx-ssl-proxy镜像可能没配置对Docker Registry需要的HTTP方法(比如PATCH),导致转发请求时出错。
验证与修复:
- 先进入容器查看默认配置:
如果配置里没明确支持PATCH方法,就自定义Nginx配置:docker exec -it nginx-ssl-proxy cat /etc/nginx/nginx.conf- 创建本地
nginx.conf文件,加入以下关键配置:server { listen 8080 ssl; server_name _; ssl_certificate /etc/ssl/certs/docker-registry; ssl_certificate_key /etc/ssl/private/docker-registry; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; auth_basic "Registry Authentication"; auth_basic_user_file /etc/nginx/docker-registry.htpasswd; location /v2/ { proxy_pass http://registry:5000/v2/; 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 $scheme; # 适配Docker Registry的特殊要求 proxy_http_version 1.1; proxy_set_header Connection ""; client_max_body_size 0; } } - 停止并删除旧的Nginx容器:
docker stop nginx-ssl-proxy && docker rm nginx-ssl-proxy - 用自定义配置重新启动容器:
docker run -d -p 8080:8080 \ -e PUBLIC_IP_ADDR=hostName \ --link registry:registry \ -v ~/certs/my-registry.crt:/etc/ssl/certs/docker-registry \ -v ~/certs/my-registry.key:/etc/ssl/private/docker-registry \ -v ~/my-registry.htpasswd:/etc/nginx/docker-registry.htpasswd \ -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \ centurylinklabs/nginx-ssl-proxy
- 创建本地
3. Docker客户端未强制使用HTTPS连接
部分情况下Docker客户端会尝试降级到HTTP,即使你配置了证书。可以强制启用HTTPS:
Windows客户端配置步骤:
- 打开Docker Desktop,进入
Docker Engine设置页面 - 添加以下配置内容:
{ "insecure-registries": [], "registry-mirrors": [], "debug": false, "experimental": false, "tls": true } - 点击
Apply & Restart重启Docker
验证步骤
完成修改后,按以下流程验证:
- 重新登录Registry:
docker login hostName:8080 - 确保镜像标签正确:
docker tag base hostName:8080/base - 再次执行推送:
docker push hostName:8080/base
如果还有问题,可以查看Nginx实时日志排查:
docker logs -f nginx-ssl-proxy
内容的提问来源于stack exchange,提问作者Mohsen
相关产品推荐
相关产品推荐

