我的目标是在树莓派上运行一个 docker registry(在
rpi
主机名后面),我能够从同一网络上的 linux PC 推送图像。我正在关注本指南:https://docs.docker.com/registry/insecure/#use-self-signed-certificates
我在我的 rpi 上做了以下步骤:
mkdir -p certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -addext "subjectAltName = DNS:rpi" -x509 -days 365 -out certs/domain.crt
docker run -d --restart=always --name registry -v $HOME/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key -p 443:443 registry
我电脑上的步骤:
scp pi@rpi:certs/domain.crt ca.crt
sudo mkdir -p /etc/docker/certs.d/rpi:5000/
sudo mv ca.crt /etc/docker/certs.d/rpi:5000/
现在,当我尝试推送图像
docker push rpi:5000/test-image
时,它失败并显示以下内容:
Get "https://rpi:5000/v2/": dialing rpi:5000 with direct connection: connecting to 192.168.1.201:5000: dial tcp 192.168.1.201:5000: connect: connection refused
如果我用 443 端口标记图像
docker push rpi:443/test-image
我得到这个错误:Get "https://rpi:443/v2/": x509: certificate is valid for 227b7008fe5910b8b4b0563bb8ebcb9e.708221ab4c2f3a622587d123822b2328.traefik.default, not rpi
如何使用自签名证书将 docker 镜像推送到远程?
您似乎正在侦听端口 443。要使其正常工作,您需要更改一些内容:
rpi.localdomain
这样的东西。如果图像路径的开头没有域,也没有端口(443 不需要),那么它将被视为 Docker Hub 上的用户名。/etc/docker/certs.d/rpi:5000/
而是/etc/docker/certs.d/rpi.localdomain/
或任何域名。放在名为5000的目录中,但连接到443意味着它没有被使用。对于第 4 步,这是我自己设置证书的脚本示例:
certdir="certs"
cert_host="registry"
cert_san="DNS:localhost,DNS:$(hostname)"
for ip in $(ip a | grep inet | awk '{print $2}' | cut -f1 -d/); do
cert_san="${cert_san},IP:$ip"
done
if [ ! -d "$certdir" ]; then
mkdir -p "$certdir"
fi
# setup a CA key
if [ ! -f "$certdir/ca-key.pem" ]; then
openssl genrsa -out "${certdir}/ca-key.pem" 4096
fi
# setup a CA cert
openssl req -new -x509 -days 365 \
-subj "/CN=Local CA" \
-key "${certdir}/ca-key.pem" \
-sha256 -out "${certdir}/ca.pem"
# setup a host key
if [ ! -f "${certdir}/key.pem" ]; then
openssl genrsa -out "${certdir}/key.pem" 2048
fi
# create a signing request
extfile="${certdir}/extfile"
openssl req -subj "/CN=${cert_host}" -new -key "${certdir}/key.pem" \
-out "${certdir}/${cert_host}.csr"
echo "subjectAltName = ${cert_san}" >${extfile}
# create the host cert
openssl x509 -req -days 365 \
-in "${certdir}/${cert_host}.csr" -extfile "${certdir}/extfile" \
-CA "${certdir}/ca.pem" -CAkey "${certdir}/ca-key.pem" -CAcreateserial \
-out "${certdir}/cert.pem"
在上面的脚本中,
ca.pem
是被复制到 /etc/docker/certs.d/${registry}/ca.crt
的内容。
在我的树莓派上运行的另一个软件(
k3s
)接管了443端口。
docker push
首先向 https://rpi.home/v2/ 发出请求并验证证书,该证书通常由 registry
容器提供。但是,如果 k3s
服务器正在运行,它会提供 /v2
url 并提供完全不同的证书。
解决方案是将不同的端口映射到容器的 443。