关键是要打通服务端tls配置、客户端信任链和禁用http回退三环:证书须含匹配域名或ip的san字段;registry需仅启用https并关闭http监听;客户端须将ca根证书置于/etc/docker/certs.d/域名:端口/ca.crt并重启docker服务。

要让 Docker 镜像仓库支持 HTTPS,关键不是只放证书,而是确保服务端能正确加载、客户端能真正信任、通信路径不降级到 HTTP。三者缺一不可。
证书必须合规且匹配访问方式
证书不能只填 CN(通用名称),现代 TLS 校验强制要求 Subject Alternative Name(SAN)字段包含实际访问地址——无论是域名还是 IP。
- 用
registry.example.com访问?证书 SAN 必须含DNS.1 = registry.example.com - 用
192.168.1.100:443直连?SAN 必须含IP.1 = 192.168.1.100 - 生成时推荐用 OpenSSL 配置文件(如
san.cnf)明确声明 SAN,避免后期 push/pull 报x509: certificate signed by unknown authority - 私钥权限设为
600,证书文件建议放在容器内安全路径(如/certs/),挂载时注意 SELinux 或 rootless 模式限制
Registry 服务端启用 HTTPS 并禁用 HTTP 回退
即使配了证书,若 Registry 仍监听并响应 HTTP 请求,中间人攻击风险仍在。必须显式关闭非加密通道。
- 裸 Registry:修改
config.yml,注释或删除整个http:段,只保留https:段,并指定certificate和key路径 - 使用 Nginx/Traefik 反代:TLS 在代理层终止,后端 Registry 可走 HTTP(仅限内网),同时关闭外部对原生端口(如 5000)的直接访问
- 验证方法:
curl -I http://registry.example.com应拒绝连接或返回 301;curl -I https://registry.example.com/v2/应返回 200 或 401
客户端必须显式信任证书(不是改系统 CA)
Docker daemon 不读系统证书池,它只认固定路径下的根证书文件。
- Linux 主机:把 CA 根证书(PEM 格式)复制为
/etc/docker/certs.d/registry.example.com:443/ca.crt,文件名必须是ca.crt - 若用 IP 访问(如
192.168.1.100:443),路径必须是/etc/docker/certs.d/192.168.1.100:443/ca.crt - 证书链不完整时,把 root CA 和中间证书合并成一个
ca.crt,顺序为 root 在前、中间在后 - 操作后必须重启 Docker:
sudo systemctl restart docker - macOS Docker Desktop:通过设置 → Resources → TLS Certificates 导入,或导入钥匙串并设为“始终信任”
生产环境优先用受信 CA 证书
自签名证书仅适合测试。生产环境应使用 Let's Encrypt 或企业内网 CA 签发的证书。
- Let’s Encrypt 可配合 certbot 自动续签,适合有公网域名的场景
- 内网环境可部署小型 CA(如 Smallstep、cfssl),统一签发和轮换证书
- 避免在 CI/CD 脚本中硬编码
--insecure-registry,这会绕过 TLS 校验,丧失传输加密意义











