由不明机构签署的“码头拉”证书

我试图从一个 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

在导入 root cert 之后,我可以看到 curl工作得很好,因为它不会抱怨 cert 错误,但是如果我使用 docker pull,我仍然有同样的问题。docker是否使用与 curl不同的卡尔特位置?在这种情况下,我如何修复 docker pull的问题?

246412 次浏览

You may need to restart the docker service to get it to detect the change in OS certificates.

Docker does have an additional location you can use to trust individual registry server CA. You can place the CA cert inside /etc/docker/certs.d/<docker registry>/ca.crt. Include the port number if you specify that in the image tag, e.g in Linux.

/etc/docker/certs.d/my-registry.example.com:5000/ca.crt

or in Windows 10:

C:\ProgramData\docker\certs.d\ca.crt
  • first create an empty json file

    cat << EOF > /etc/docker/daemon.json
    { }
    EOF
    
  • than run the following to add certs

    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
    

works without restart

OR

import the cert to system like

  • save the cert to the file , like the command above (the port is crucial, no need for the protocol)

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

    sudo cp ca.crt /usr/local/share/ca-certificates/
    
  • run update-ca-certificates

    sudo update-ca-certificates
    
  • restart docker !

Here is a quick solution:

  • Edit or create the file /etc/docker/daemon.json and add insecure-registries:

example for docker.squadwars.org:

{
"insecure-registries" : ["docker.squadwars.org:443"]
}
  • Restart docker daemon
systemctl restart docker
  • Create a directory with the same name of the host .

example for docker.squadwars.org:

mkdir -p /etc/docker/certs.d/docker.squadwars.org
  • Get the certificate and save it to the created directory.
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

For my case, the error was on "docker login" command.

The solution I found for my ubuntu:

I downloaded the crt file via firefox (lock icon in the url adress bar) and save it : ~/mydomain:1234.crt

After that :

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

By default docker keeps a local Certificate store, in Centos:/etc/sysconfig/docker. In Organizations, the servers usually comes preinstalled with it's own Root Cert. So if you use cert issued by the organization, docker will not be able to find the organization's Root Cert. when it refers to its local store. So either you can remove the reference to its local store in /etc/sysconfig/docker or you can delete it's local Certificate store (Centos:/etc/docker/certs.d). Restarting docker service after you make the change will resolve this issue.

For anyone who is using CentOS 7, this is what worked for me:

  • Obtain necessary certificate (e.g. from your company)
  • Copy the certificate to ca-trust location:
sudo cp -p abc.crt /etc/pki/ca-trust/source
  • Update the certificate:
sudo update-ca-trust extract
  • Reload daemon and restart docker:
sudo systemctl daemon-reload
sudo systemctl restart docker

For the MacOS Docker Desktop user:

Go to your repository's URL in a browser. You may have to accept all security prompts.

Click on the padlock 🔓on the address bar, then click on "Connection is secure/Certificate is valid" (on Chrome) or "Show Certificate" (on Safari), and a certificate window popup will appear.

For Chrome users, click on tab "Details" and button "Export" at the bottom to export the certificate file.

For Safari users, Click and hold down on the big paper icon of the certificate and drag it to a folder of your preference, or the desktop.

Open your terminal (make sure to replace the last argument with the location of your file):

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

Restart your docker engine.

For me I ended up doing this to get it to work:

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

In my case I had the same problem inside a KIND container. Curl didn't work there.

curl https://google.com
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html


curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
    

and the update-ca-certificate command didn't work for me. I had to append the CA certificate to the /etc/ssl/certs/ca-certificates.crt file:

cat /ca_cert.pem >>  /etc/ssl/certs/ca-certificates.crt

And then curl worked properly.

update ca without restart docker,and use root ca.cert, replace registry.clickpaas.tech with your domain:

sudo yum -y update ca-certificates;
sudo mkdir -p /etc/docker/certs.d/registry.clickpaas.tech/;
sudo cp /etc/ssl/certs/ca-bundle.crt /etc/docker/certs.d/registry.clickpaas.tech/;

Didn't see this mentioned in any of the answers. Here is the official docker documentation for setting up certs for each specific domain. This goes along with the most accepted answer. https://docs.docker.com/engine/security/certificates/

Path for:

  • Linux: /etc/docker/certs.d/[domain of relevent cert]/[cert].crt
  • Windows: C:/ProgramData/Docker/certs.d/[domain of relevent cert]/[cert].crt


If you are using WSL or WSL2 you will place the cert in the windows location.

A key problem that I encountered was that the extension of the cert is important to docker. I was not able to resolve the issue with a .cer ssl cert but was with .crt.

for 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

In Windows you can just follow instruction (much easier than other approaches which I found):

Open Windows Explorer, right-click the certificate, and choose Install certificate.

Then, select the following options:

  • Store location: local machine
  • Check place all certificates in the following store
  • Click Browser, and select Trusted Root Certificate Authorities
  • Click Finish

After adding the CA certificate to Windows, restart Docker Desktop
for Windows.

Also it's important to choose correct options!

Here I found this instruction: https://docs.docker.com/registry/insecure/#windows