"docker pull"证书签名的颁发机构未知

119
我正在尝试从Docker注册表中拉取一个Docker镜像,但遇到了以下问题:
$ docker pull <docker registry>/<image name>/<tag> 
Error response from daemon: Get <docker registry>/v1/_ping: x509: certificate signed by unknown authority

我试过用"curl"命令,但是也收到了类似的错误信息:
 curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.

我下载了CA证书,并使用以下命令将其导入到服务器(RedHat Linux 7)中:

cp root_cert.cer /etc/pki/ca-trust/source/anchors/
update-ca-trust

导入根证书后,我可以看到curl正常工作,不会出现证书错误的提示,但如果我使用docker pull仍然会遇到同样的问题。是docker使用的ca证书位置与curl不同吗?在这种情况下,我应该如何解决docker pull的问题?


3
这里的答案没有解决我的问题,官方文档为我提供了答案 - https://docs.docker.com/registry/insecure/。对于我来说,Red Hat和Ubuntu的证书路径和更新命令是不同的。 - LostNomad311
@LostNomad311 谢谢,文档也帮我解决了问题。 - Moses
在我的情况下,我使用Linux在vbox中。第一次尝试时出现了这个错误。但是在第二次尝试中,错误消失了。 - JRichardsz
14个回答

119
更新操作系统证书后,通常需要重新启动Docker服务以使其检测到这个变化。一般情况下,可以通过以下方式来完成:
sudo systemctl restart docker

或者对于非systemd环境:
sudo service docker restart

Docker确实有一个额外的位置,您可以使用它来信任单个注册服务器CA。您可以将CA证书放置在/etc/docker/certs.d/<docker registry>/ca.crt中。如果您在镜像标签中指定了端口号,例如在Linux中,请包括该端口号。
/etc/docker/certs.d/my-registry.example.com:5000/ca.crt

或者适用于基于Snap的安装方式:
/var/snap/docker/~current/etc/docker/certs.d/my-registry.example.com:5000/ca.crt

或者在Windows 10中:
C:\ProgramData\docker\certs.d\ca.crt

如果您还没有证书,可以使用openssl提取它。请注意,这将隐式地信任注册表当前所说的证书,从而使您容易受到中间人攻击。如果您不处于临时环境中,这可能作为TOFU(首次使用时信任)很有用。
openssl s_client -showcerts -connect my-registry.example.com:5000 < /dev/null \
  | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

13
谢谢!我的更改后,service docker restart修复了问题!另一个提示很有用,因为我可以信任特定的Docker注册表而不影响其他应用程序。 - Chen Xie
注意:在Ubuntu中使用snap时,正确的路径为/var/snap/docker/~current/etc/docker/certs.d。 - Michael Feinstein
完成以上步骤后,我摆脱了“x509:证书已被未知颁发机构签名”的问题,但随后出现了“401 未经授权”的错误。为解决此问题,我需要执行“docker login <docker registry>”。 - asherbret

70
  • 首先创建一个空的 JSON 文件

cat << EOF > /etc/docker/daemon.json
{ }
EOF
运行以下命令来添加证书。
openssl s_client -showcerts -connect [registry_address]:[registry_port] < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /etc/docker/certs.d/[registry_address]/ca.crt

无需重启即可运行

或者

将证书导入到系统中,如下所示

  • 将证书保存至文件,像上面的命令一样(端口很关键,协议不需要)

openssl s_client -showcerts -connect [registry_address]:[registry_port] < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ca.crt
  • 将它复制到 /usr/local/share/ca-certificates/

  • sudo cp ca.crt /usr/local/share/ca-certificates/
    
    运行 update-ca-certificates。
    sudo update-ca-certificates
    
  • 重新启动 Docker!


  • 3
    XXX: 创建空的/etc/docker/daemon.json并使用systemctl restart docker重启docker导致我的docker守护程序崩溃。我不得不删除创建的文件才能再次运行它。 - validname
    1
    在我的情况下,我还必须在/etc/docker/daemon.json中包含{"insecure-registries":["<registry_address>:<registry_port>"]}才能使其正常工作。 - Ava
    1
    谢谢,它像魔法一样奏效了,但我需要使用sudo进行复制。 - anquegi
    1
    注意:如果您正在使用Snap,则正确的路径为: /var/snap/docker/~current/etc/docker/certs.d - Michael Feinstein
    1
    请创建一个有效的空JSON文件/etc/docker/daemon.json,而不是空的/etc/docker/daemon.json。一个有效的空json daemon.json文件只包含花括号,并在括号之间留有空格!!! --> { } - nix
    1
    上帝保佑你,哈哈。完美地工作了,无需重新启动。非常感谢! - Danilo M. Oliveira

    55

    以下是一个快速解决方案:

    • 编辑或创建文件/etc/docker/daemon.json并添加insecure-registries

    docker.squadwars.org的示例:

    {
        "insecure-registries" : ["docker.squadwars.org:443"]
    }
    
    • 重启Docker守护进程
    systemctl restart docker
    
    • 创建一个与主机名称相同的目录。

    以docker.squadwars.org为例:

    mkdir -p /etc/docker/certs.d/docker.squadwars.org
    
    • 获取证书并将其保存到创建的目录中。
    ex +’/BEGIN CERTIFICATE/,/END CERTIFICATE/p’ <(echo | openssl s_client -showcerts -connect docker.squadwars.org:443) -scq > /etc/docker/certs.d/docker.squadwars.org/docker_registry.crt
    

    5
    如果您指示 Docker 为“不安全”,为什么需要安装证书? - Eugen Konkov

    29

    针对 MacOS Docker Desktop 用户:

    在浏览器中打开您的存储库 URL。 您可能需要接受所有安全提示。

    单击地址栏上的挂锁,然后单击“连接安全/证书有效”(在 Chrome 上)或“显示证书”(在 Safari 上),将弹出证书窗口。

    对于 Chrome 用户,请单击“详细信息”选项卡和底部的“导出”按钮以导出证书文件。

    对于 Safari 用户,请单击并按住证书的大纸片图标,将其拖到您喜欢的文件夹或桌面上。

    打开您的终端(确保将最后一个参数替换为您的文件位置):

    security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain-db ~/<<<somefolder>>>/<<<yourserver.cer>>>
    

    重新启动你的docker引擎。


    对于在MacOS上的Docker桌面版,您可以将证书放入~/.docker/certd.d/<REGISTRY_NAME>:<PORT>/。更多信息请参考- https://docs.docker.com/desktop/faqs/macfaqs/#how-do-i-add-tls-certificates - undefined

    13

    对于我的情况,错误出现在“docker登录”命令上。

    我在Ubuntu上找到的解决方案:

    我通过Firefox(网址栏中的锁图标)下载了crt文件并保存为:~/mydomain:1234.crt

    之后:

    cp ~/mydomain:1234.crt /usr/local/share/ca-certificates/
    update-ca-certificates
    service docker restart
    

    它在客户端还是服务器上? - Sam
    这对我也起作用了。Ubuntu: 22.04 - DhaneshM
    "update-ca-certificates" 和 "service docker restart" 对我有用。 - BarzanHayati

    12

    对于Ubuntu 20

    sudo update-ca-certificates --fresh
    
    openssl s_client -showcerts -verify 5 -connect registry-1.docker.io:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | tee ~/docker.crt
    
    openssl s_client -showcerts -verify 5 -connect production.cloudflare.docker.com:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | tee ~/docker-com.crt
    
    sudo cp ~/docker-com.crt /usr/local/share/ca-certificates/.
    
    sudo cp ~/docker.crt /usr/local/share/ca-certificates/
    
    
    sudo update-ca-certificates
    sudo service docker restart
    

    我只想补充一下,证书必须具有 .crt 扩展名。 - Miroslav

    5

    如果您正在使用CentOS 7,这是对我有效的方法:

    • 获取必要的证书(例如来自您公司)
    • 将证书复制到ca-trust位置:
    sudo cp -p abc.crt /etc/pki/ca-trust/source
    
    • 更新证书:
    sudo update-ca-trust extract
    
    • 重新加载守护进程并重启Docker:
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    

    谢谢您的评论,我已经修复了拼写错误 :) - Minh Nguyen

    5

    对于我来说,最终我做了以下操作才使其正常工作:

    sudo cp -p abc.crt /etc/pki/ca-trust/source/anchors
    sudo update-ca-trust
    sudo update-ca-trust extract
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    

    3

    在任何答案中都没有提到过这一点。这是用于为每个特定域设置证书的官方docker文档。这与最被接受的答案相符。https://docs.docker.com/engine/security/certificates/

    路径为:

    • Linux:/etc/docker/certs.d/[相关证书的域]/[证书].crt
    • Windows:C:/ProgramData/Docker/certs.d/[相关证书的域]/[证书].crt


    如果您使用WSL或WSL2,则将证书放置在Windows位置。

    我遇到的一个关键问题是证书的扩展名对于docker很重要。我无法通过.cer ssl证书解决这个问题,但可以通过.crt解决。


    1

    在Windows中,您只需按照以下说明操作(比我发现的其他方法要简单得多):

    打开Windows资源管理器,右键单击证书,选择安装证书。

    然后,选择以下选项:

    • 存储位置:本地计算机
    • 检查放置所有证书的位置
    • 单击浏览,选择受信任的根证书颁发机构
    • 单击完成

    将CA证书添加到Windows后,重新启动Windows版Docker Desktop。

    此外,选择正确的选项也很重要!

    在这里,我找到了这个指南: https://docs.docker.com/registry/insecure/#windows


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接