本文使用的docker registry并非官方的registry, 和official的registry的最大区别是: 该registry是基于busybox来实现,所以里面没有任何openssl相关的信息, 也没有任何证书的信息.
docker默认情况下,连接registry 时,会使用https连接,如果我们的registry只是支持http连接,那么便会发生如下的错误:
[root@localhost ~]# docker pull -a 192.168.0.110:5000/panda/mysql
Trying to pull repository 192.168.0.110:5000/panda/mysql ...
Get https://192.168.0.110:5000/v1/_ping: http: server gave HTTP response to HTTPS client
#这里就是说,客户端发送了https 请求,但是server给的response是http响应;这里客户端的请求就是docker pull -a 192.168.0.110:5000/panda/mysql。
为了解决上述问题,我们有如下的A, B 两种方案: A. 配置docker 允许接收http响应,而不单单是接受https相应;具体方法如下:
--insecure-registry=[]
Enable insecure registry communication, i.e., enable un-encrypted and/or
untrusted communication.
List of insecure registries can contain an element with CIDR notation to
specify a whole subnet. Insecure registries accept HTTP and/or accept HTTPS
with certificates from unknown CAs.
Enabling --insecure-registry is useful when running a local registry.
However, because its use creates security vulnerabilities it should ONLY be
enabled for testing purposes. For increased security, users should add their
CA to their system's list of trusted CAs instead of using
--insecure-registry.
所以可以在docker.serivce 文件中,添加启动参数 : --insecure-registry=192.168.0.110:5000 , 然后restart docker.service 来解决上面的问题:
#修改之后,有如下的参数:
[root@localhost docker]# grep insecure-registry /usr/lib/systemd/system/docker.service
--insecure-registry=192.168.0.110:5000
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker.service
[root@localhost docker]# docker pull 192.168.0.110:5000/panda/mysql:v1
Trying to pull repository 192.168.0.110:5000/panda/mysql ...
v1: Pulling from 192.168.0.110:5000/panda/mysql
Digest: sha256:258255419e9b96b50bc0114dbe7f9a313cfa6552967b6472f174392fc4cf66e4
Status: Image is up to date for 192.168.0.110:5000/panda/mysql:v1
[root@localhost docker]#
B. 对registry配置https 访问支持:
[root@localhost cert_test]# ls -l
total 24
-rw-------. 1 root root 1359 Aug 18 21:31 CA_Cert.pem #自签名的根证书,docker客户端需要信任该证书
-rw-------. 1 root root 1675 Aug 18 21:20 CA_Key.key
-rw-r--r--. 1 root root 1021 Aug 18 17:23 my_cert.csr
-rw-------. 1 root root 4509 Sep 17 21:49 my.crt #此证书为registry使用的证书;
-rw-r--r--. 1 root root 1679 Aug 18 17:18 myprivate.key #my.crt证书所对应的私钥
[root@localhost cert_test]#
#首先把/root/cert_test/ mapping 到registry 容器的/etc/cert.d目录,然后,设置变量如下:
#REGISTRY_HTTP_TLS_CERTIFICATE=/etc/cert.d/my.crt
#REGISTRY_HTTP_TLS_KEY=/etc/cert.d/myprivate.key
[root@localhost ~]# docker run -d -v /var/my_registry/:/var/lib/registry -v /root/cert_test/:/etc/cert.d -e REGISTRY_HTTP_TLS_CERTIFICATE=/etc/cert.d/my.crt -e REGISTRY_HTTP_TLS_KEY=/etc/cert.d/myprivate.key -p 5000:5000 my_registry
4df7d9af67de55149670f6be54e6683d38ec13d8a428ed778442e812500f2d63
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4df7d9af67de my_registry "/my_entry.sh /etc..." 4 seconds ago Up 3 seconds 0.0.0.0:5000->5000/tcp jovial_newton
[root@localhost ~]#
#没有添加CA到CA Trust列表里面,报如下错误:
[root@localhost cert_test]# curl -I https://www.my.com:5000/
curl: (60) Peer's Certificate issuer is not recognized.
More details here: http://curl.haxx.se/docs/sslcerts.html
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.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
[root@localhost cert_test]#
#尝试添加CA到CA TRUST列表,然后再次用curl验证;
[root@localhost cert_test]# cp CA_Cert.pem /etc/pki/ca-trust/source/anchors/
[root@localhost cert_test]# update-ca-trust
[root@localhost cert_test]# curl -I https://www.my.com:5000/
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Wed, 02 Oct 2019 15:23:49 GMT
[root@localhost cert_test]#
#用REST API尝试获取registry中的images.
[root@localhost ~]# curl -XGET https://www.my.com:5000/v2/_catalog
{"repositories":["panda/my_baseimage","panda/my_registry"]}
[root@localhost ~]# vim /usr/lib/systemd/system/docker.service #编辑docker.service文件,取消 --insecure-registry=192.168.0.110:5000的配置
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker.service #重启docker 服务;
#启动registry 容器,并指定ssl的相关证书
[root@localhost ~]# docker run -d -v /var/my_registry/:/var/lib/registry -v /root/cert_test/:/etc/cert.d -e REGISTRY_HTTP_TLS_CERTIFICATE=/etc/cert.d/my.crt -e REGISTRY_HTTP_TLS_KEY=/etc/cert.d/myprivate.key -p 5000:5000 my_registry
ce31b92655e31d784e338f05067d0c760827903d110353218ba87ae5423cdf49
#以下的docker pull 是成功的;
[root@localhost cert_test]# docker pull -a www.my.com:5000/panda/my_registry
Trying to pull repository www.my.com:5000/panda/my_registry ...
v1: Pulling from www.my.com:5000/panda/my_registry
Digest: sha256:0614f2636b7dc16c8f95be8fff1af4252719955440317fb170abd29863a6ad37
Status: Downloaded newer image for www.my.com:5000/panda/my_registry
[root@localhost cert_test]#
#停掉支持ssl的registry, 用不支持ssl的registry,重新pull 下进行测试:
[root@localhost cert_test]# docker run -d -v /var/my_registry/:/var/lib/registry -p 5000:5000 my_registry
255446ba982e8661420bd34af79a7c4a5c9d1be52211c66ef6c62f4e7b439059
#用curl测试,5000端口不支持ssl. 但是支持常规的http
[root@localhost cert_test]# curl -I https://www.my.com:5000/
curl: (35) SSL received a record that exceeded the maximum permissible length.
[root@localhost cert_test]# curl -I http://www.my.com:5000/
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Wed, 02 Oct 2019 15:33:29 GMT
#docker pull 出现文章开头的报错;
[root@localhost cert_test]# docker pull -a www.my.com:5000/panda/my_registry
Trying to pull repository www.my.com:5000/panda/my_registry ...
Get https://www.my.com:5000/v1/_ping: http: server gave HTTP response to HTTPS client
[root@localhost cert_test]#
写了这么多,其实要开启ssl连接支持,只需要如下的条件: A. 对于registry,运行容器时需要以下两个参数的值: REGISTRY_HTTP_TLS_CERTIFICATE , 用于指定https证书的位置; REGISTRY_HTTP_TLS_KEY, 用于指定https证书对应的私钥key的位置; B. 而对于docker客户端: 1.需把自签名的CA证书加入信任列表,不同os 操作方法不同,eg: centos是用update-ca-trust 。 2.访问registry的时候,指定的地址必须和服务器证书中指定的地址一致,否则证书报错;
本文原创,转载请注明出处 参考:https://docs.docker.com/registry/deploying/#run-an-externally-accessible-registry