使用自签名证书将本地 Docker 图像推送到私有存储库

Pushing a local Docker image to a private repository with a self-signed certificate

我正在尝试将图像 foo/bar 从我的本地 Docker 注册表推送到 OpenShift 3.11 上的注册表 运行(实际上是 Minishift v1. 33.0+ba29431).

注册表位于 192.168.64.3:2376,需要 HTTPS 连接。它使用自签名证书。

首先我复制新图片的标签:

docker tag foo/bar 192.168.64.3:2376/app/foo/bar

这就成功了。然后我尝试推送:

$ docker push 192.168.64.3:2376/app/foo/bar
The push refers to repository [192.168.64.3:2376/app/foo/bar]
Get https://192.168.64.3:2376/v2/: x509: certificate signed by unknown authority

或者,当 Docker 配置为允许在 192.168.64.0/24 中使用不安全的注册表时,它会与服务器通信而不是禁用证书验证:

$ docker push 192.168.64.3:2376/app/foo/bar
The push refers to repository [192.168.64.3:2376/app/foo/bar]
Get http://192.168.64.3:2376/v2/: EOF

文档说对于不安全的注册表,它应该 "First, try using HTTPS. If HTTPS is available but the certificate is invalid, ignore the error about the certificate. If HTTPS is not available, fall back to HTTP." 所以我不希望看到 EOF 错误。

我也无法告诉 Docker 使用 Minishift 证书,因为它突然失去了与本地 Docker 守护进程通信的能力(它应该使用 Unix 域套接字,而不是 tcp ://localhost:2376):

$ export DOCKER_TLS_VERIFY="1"
$ export DOCKER_CERT_PATH="/Users/rzg/.minishift/certs"
$ docker push 192.168.64.3:2376/app/foo/bar
Cannot connect to the Docker daemon at tcp://localhost:2376. Is the docker daemon running?

这是 Docker 我正在使用的版本:

Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:39 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     false

你提到的那两个环境变量是为了让 docker command-line 工具与 Docker 守护进程对话。您通常不需要设置它们。 (另请注意,端口 2376 是 Docker API HTTP-over-TLS 的常规端口,但没有什么能阻止您将其用于注册表。)

您正在尝试配置 Docker 守护程序以与您信任的远程注册表对话。 The dockerd reference says about secure registries:

A secure registry uses TLS and a copy of its CA certificate is placed on the Docker host at /etc/docker/certs.d/myregistry:5000/ca.crt.

因此在您的设置中,您需要找到注册表的 CA 证书,并将其放入 /etc/docker/certs.d/192.168.64.3:2376/ca.crt,然后重新启动 Docker 守护程序。

Securing and Exposing the Registry 下的 OpenShift OKD 文档中也对此进行了描述(请参阅 "Manually Securing the Registry",尤其是其步骤 12 和 13)。

根据文档:

您可以将您的客户证书和密钥放入

~/.docker/certs.d/<MyRegistry>:<Port>/client.cert

~/.docker/certs.d/<MyRegistry>:<Port>/client.key

https://docs.docker.com/docker-for-mac/faqs/#how-do-i-add-custom-ca-certificates

或者您配置一个凭据存储并在那里加载证书,然后在 ~/.docker/config json

中配置存储

此处的文档:https://docs.docker.com/engine/reference/commandline/login/

Docker 客户端需要配置为 (i) 接受由 CA 证书签名的私人注册表的证书,以及 (ii) 提供授权的客户端证书。

Minishift 将其所有证书文件放在 ~/.minishift/certs 中。这包括 CA 证书 (ca.pem)、客户端证书 (cert.pem) 和客户端私钥 (key.pem)。

此示例查询证明所有三个要素都会导致连接成功:

curl \
    --cacert ~/.minishift/certs/ca.pem \
    --cert ~/.minishift/certs/cert.pem \
    --key ~/.minishift/certs/key.pem \
    https://$(minishift ip):2376/v2/info

在 macOS 上,我们需要按照 this part of Docker's documentation 将 CA 证书安装到钥匙串:

security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain ~/.minishift/certs/ca.pem

并链接到客户端证书和密钥:

mkdir -p ~/.docker/certs.d/$(minishift ip):2376/
ln -s ~/.minishift/certs/cert.pem ~/.docker/certs.d/$(minishift ip):2376/client.cert
ln -s ~/.minishift/certs/key.pem ~/.docker/certs.d/$(minishift ip):2376/client.key

最后,重启Docker for Mac然后push。