Docker登录私有仓库报错x509: certificate signed by unknown authority
问题结论
该报错和website主机本地配置的独立Let's Encrypt证书无任何冲突。x509: certificate signed by unknown authority的本质是Docker客户端无法验证镜像仓库返回的TLS证书信任链,和客户端本地存储的其他域名证书完全无关。
针对你两个疑问的解答
1. 为什么database主机无需手动拷贝证书就能正常登录?
网上所有"手动拷贝仓库证书到客户端"的方案,仅适用于自签名CA/私有CA签发仓库证书的场景。你用的是Let's Encrypt签发的公共可信证书,只要客户端系统安装了最新的公共CA根证书包,本来就不需要手动导入证书。
database主机能正常登录、website主机报错,99%的原因是你给registry容器挂载的证书不是完整链:
- Let's Encrypt生成的证书文件中,
cert.pem仅包含站点本身的证书,不含中间CA证书;只有fullchain.pem是包含完整信任链的证书文件。如果你当前挂载的domain.crt是重命名后的cert.pem,仓库返回的握手信息里就会缺失中间证书,部分没有提前缓存对应中间CA的客户端就会报未知权威机构错误。 - database主机能正常登录只有两种可能:要么该主机的
ca-certificates包版本刚好包含对应中间CA、或是之前访问过使用同一中间CA签发的站点,本地已经缓存了中间证书;要么你之前在该主机上配置过Docker的insecure-registry参数,只是没有留存配置记录。
2. 证书续期的处理方式
只要你正确配置registry使用Let's Encrypt的完整链证书,续期时完全不需要对客户端做任何操作:
- 公共CA的根证书和中间证书默认预装在所有主流操作系统的信任库中,客户端会自动完成证书校验,不需要你手动拷贝任何文件。
- Let's Encrypt续期完成后,你只需要重启registry容器让它加载新的证书文件即可,没有额外的客户端维护成本。
修复步骤
- 先修正registry容器的启动参数,不要挂载整个
live目录(Let's Encrypt的live目录下文件是软链接,直接挂载目录容易出现容器内无法读取真实文件的问题),直接挂载完整链证书和私钥,加只读权限更安全:
# 先删掉旧的故障容器 docker rm -f registry # 启动新的registry容器 docker run -d --restart=always --name registry \ -v /etc/letsencrypt/live/vmreg.com/fullchain.pem:/certs/domain.crt:ro \ -v /etc/letsencrypt/live/vmreg.com/privkey.pem:/certs/domain.key:ro \ -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \ -p 5000:5000 \ registry:2
- 分别在两台客户端主机执行校验命令,确认证书链正常:
curl -v https://vmreg.com:5000/v2/
如果命令返回401 Unauthorized属于正常现象,说明TLS握手已经成功,只是需要登录认证;如果还是报证书错误,就更新两台主机的CA证书包:
apt update && apt install -y ca-certificates && update-ca-certificates systemctl restart docker
- 后续配置Let's Encrypt续期钩子,续期完成后自动重启registry容器加载新证书即可,不需要对客户端做任何额外操作。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

