搭建docker私有倉庫
搭建docker私倉,可以使用docker官方提供的registry鏡像。該鏡像目前有2.0,2.3和2.3.1版本。它只與1.6.0以上版本的docker兼容。搭建私倉的步驟如下:
一:無代理、無認證的registry
1:下載registry鏡像:
docker pull registry:2
這裏必須加上標簽”:2”,否則的話,不加標簽的registry,實際上下載的是標簽為”latest”的registry鏡像,則不能使用下面的nginx代理鏡像:containersol/docker-registry-proxy
2:創建registry容器:
在registry:2創建的私有倉庫中,上傳的鏡像保存在容器的/var/lib/registry目錄下。創建registry:2的容器時,會自動創建一個數據卷(Data Volumes),數據卷對應的宿主機下的目錄一般為:/var/lib/docker/volumes/XXX/_data。
可以在創建registry:2的容器時,通過-v參數,修改這種對應關系:
docker run -d -p 5000:5000 --restart=always –v \ /opt/docker/registry/data:/var/lib/registry --name docker-registry registry:2
除了可以將數據保存在當前主機的文件系統上,registry也支持其他基於雲的存儲系統,比如S3,Microsoft Azure, Ceph Rados, OpenStack Swift and Aliyun OSS等。可以在配置文件中進行配置:https://github.com/docker/distribution/blob/master/docs/configuration.md#storage
以上其實已經創建好了一個docker私有倉庫,但是這時候向其push或者pull時還是有問題的:
[@hh_93_197 /]# docker tag hello-world 192.168.1.104:5000/hello-world [@hh_93_197 /]# docker push 192.168.1.104:5000/hello-world The push refers to a repository [192.168.1.104:5000/hello-world] unable to ping registry endpoint https://192.168.1.104:5000/v0/ v2 ping attempt failed with error: Get https://192.168.1.104:5000/v2/: tls: oversized record received with length 20527 v1 ping attempt failed with error: Get https://192.168.1.104:5000/v1/_ping: tls: oversized record received with length 20527
這是因為從docker1.3.2版本開始,使用registry時,必須使用TLS保證其安全。
最簡單的解決辦法是,在需要連接該私有倉庫的所有客戶端docker宿主機上,修改dockerdaemon的配置文件,增加insecure-registry參數。
比如,對於Redhat7的宿主機來說,新增文件/etc/systemd/system/docker.service.d/docker.conf,其內容配置如下:
[Service] ExecStart= ExecStart=/usr/bin/docker daemon -H fd:// --insecure-registry=192.168.1.104:5000
然後,重啟docker:
[root@localhost /]# systemctl daemon-reload
[root@localhost /]# service docker restart
此時就可以使用該私有倉庫了。
但是,上面這種配置方式既不安全(所有人都可以push或pull),也很不方便(使用該私有倉庫的所有宿主機上都這樣進行配置)。
下面是帶有認證的registry私倉構建過程:
二:無代理,有認證的registry
使用TLS認證registry容器時,必須有證書。一般情況下,是要去認證機構購買簽名證書。這裏使用openssl生成自簽名的證書。
1:生成自簽名證書
一般情況下,證書只支持域名訪問,要使其支持IP地址訪問,需要修改配置文件openssl.cnf。
在Redhat7系統中,文件所在位置是/etc/pki/tls/openssl.cnf。在其中的[ v3_ca]部分,添加subjectAltName選項:
[ v3_ca ]
subjectAltName = IP:192.168.1.104
接下來就是生成自簽名的證書:
mkdir -p /opt/docker/registry/certs openssl req -x509 -days 3650 -nodes -newkey rsa:2048 -keyout /opt/docker/registry/certs/domain.key -out /opt/docker/registry/certs/domain.crt
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server‘s hostname) []:192.168.1.104:5000
Email Address []:
這裏的服務器域名寫成”192.168.1.104:5000”,後續就使用該地址訪問私倉。其余項直接回車即可。
2:創建帶有TLS認證的registry容器
docker run -d --name docker-registry-no-proxy --restart=always -v /opt/docker/registry/data:/var/lib/registry -u root -p 192.168.1.104:5000:5000 -v /opt/docker/registry/certs:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key registry:2
3:配置客戶端宿主機
目前,已經搭建好了一個registry私有倉庫了。但是,訪問該私倉還是會報錯:
# docker pull 192.168.1.104:5000/redis Using default tag: latest Error response from daemon: unable to ping registry endpoint https://192.168.1.104:5000/v0/ v2 ping attempt failed with error: Get https://192.168.1.104:5000/v2/: x509: certificate signed by unknown authority v1 ping attempt failed with error: Get https://192.168.1.104:5000/v1/_ping: x509: certificate signed by unknown authority
這是因為客戶端宿主機上沒有相應的證書。需要把registry所在主機上,剛生成的證書:
/opt/docker/registry/certs/domain.crt
復制到客戶端宿主機上的:
/etc/docker/certs.d/192.168.1.104:5000/ca.crt
之後,就可以使用該私倉了:
# docker pull 192.168.1.104:5000/redis Using default tag: latest latest: Pulling from redis 80ab95908a2b: Pull complete a3ed95caeb02: Pull complete 47a0d79f89b9: Pull complete 7190081b1686: Pull complete fe09c22d81ac: Pull complete a5eae2bcc645: Pull complete 662723161f77: Pull complete b568670a8ccd: Pull complete a1a961e320bc: Pull complete Digest: sha256:769ac80a4711258ec4d6d325f3ad31fbce3bbfa006d5f8aae94c94917dfb0384 Status: Downloaded newer image for 192.168.1.104:5000/redis:latest
更好的方式是使用nginx代理,由nginx提供https的ssl的認證和basicauthentication。方法如下:
三:nginx代理,域名訪問的registry
1:生成自簽名證書:
mkdir -p /opt/docker/registry/conf openssl req -x509 -days 3650 -nodes -newkey rsa:2048 -keyout /opt/docker/registry/conf/docker-registry.key -out /opt/docker/registry/conf/docker-registry.crt
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server‘s hostname) []:hh.registry.com
Email Address []:
這裏的服務器域名寫成”hh.registry.com”,其余項直接回車即可。
2:創建能夠訪問倉庫的用戶名和密碼
htpasswd -b -c -d /opt/docker/registry/conf/docker-registry.htpasswd admin admin
這裏的用戶名和密碼都是admin
3:運行nginx
這裏使用容器containersol/docker-registry-proxy運行nginx:
docker run -d -p 443:443 --name docker-registry-proxy -e REGISTRY_HOST="docker-registry" -e REGISTRY_PORT="5000" -e SERVER_NAME="hh.registry.com" --link docker-registry:docker-registry -v /opt/docker/registry/conf/docker-registry.htpasswd:/etc/nginx/.htpasswd:ro -v /opt/docker/registry/conf:/etc/nginx/ssl:ro containersol/docker-registry-proxy
註意,這裏的環境變量SERVER_NAME也要設置成”hh.registry.com”.
目前,就已經搭建好了一個registry私有倉庫了。但是,還需要在使用它的客戶端宿主機執行以下的操作。比如在私有倉庫所在的主機上使用它,也要執行以下步驟:
4:修改/etc/hosts文件,增加以下內容,以使客戶端宿主機可以解析域名”hh.registry.com”
192.168.1.104 hh.registry.com
5:復制證書
mkdir -p /etc/docker/certs.d/hh.registry.com
cp /opt/docker/registry/conf/docker-registry.crt /etc/docker/certs.d/hh.registry.com/ca.crt
這裏是在registry所在主機上進行的操作。如果是其他docker宿主機,需要遠程復制該crt文件。
客戶端宿主機配置好以後,通過下面的方式驗證私有倉庫的可用性:
6:列出私有倉庫上的所有鏡像
#curl -X GET https://admin:[email protected]/v2/_catalog -k {"repositories":["hello-world","ubuntu"]}
7:登陸
#docker login -u admin -p admin hh.registry.com WARNING: login credentials saved in /root/.docker/config.json Login Succeeded
8:pull鏡像
#docker pull hh.registry.com/ubuntu Using default tag: latest latest: Pulling from ubuntu 5a132a7e7af1: Pull complete fd2731e4c50c: Pull complete 28a2f68d1120: Pull complete a3ed95caeb02: Pull complete Digest: sha256:9409f5e54fdc68ef3f0aae3c5ffac22bfe2aabd0b363a4bdbe5292c93b75a661 Status: Downloaded newer image for hh.registry.com/ubuntu:latest
9:push鏡像
# docker tag registry.aliyuncs.com/ddbmh/redis hh.registry.com/redis # docker push hh.registry.com/redis The push refers to a repository [hh.registry.com/redis] 5f70bf18a086: Mounted from ubuntu 7986f971c50f: Pushed 590d3336f33c: Pushed 4458b6e6f424: Pushed 39d2b75cc73d: Pushed cbc6c973b349: Pushed d53a2702e023: Pushed 5bca8d976dd8: Pushed 603fd967d41c: Pushed latest: digest: sha256:769ac80a4711258ec4d6d325f3ad31fbce3bbfa006d5f8aae94c94917dfb0384 size: 3823
10:再次列出私有倉庫中的所有鏡像
# curl -X GET https://admin:[email protected]/v2/_catalog -k {"repositories":["hello-world","redis","ubuntu"]}
四:nginx代理,IP訪問的registry
以上的步驟中,訪問私倉只能使用域名”hh.registry.com”,如果使用IP訪問,則會報錯:
#docker login -u admin -p admin -e a 192.168.1.104 Error response from daemon: invalid registry endpoint https://192.168.1.104/v0/: unable to ping registry endpoint https://192.168.1.104/v0/ v2 ping attempt failed with error: Get https://192.168.1.104/v2/: x509: cannot validate certificate for 192.168.1.104 because it doesn‘t contain any IP SANs ...
如果想用IP地址訪問,則執行以下的步驟:
1:在文件/etc/pki/tls/openssl.cnf的[ v3_ca ]部分,添加subjectAltName選項
[ v3_ca ]
subjectAltName = IP:192.168.1.104
2:重新生成證書
openssl req -x509 -days 3650 -nodes -newkey rsa:2048 -keyout /opt/docker/registry/conf_ip/docker-registry.key -out /opt/docker/registry/conf_ip/docker-registry.crt
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server‘s hostname) []:hh.registry.com
Email Address []:
這裏的服務器域名還是寫成”hh.registry.com”即可。其余項直接回車即可。
3:創建能夠訪問倉庫的用戶名和密碼
htpasswd -b -c -d /opt/docker/registry/conf_ip/docker-registry.htpasswd admin admin
這裏的用戶名和密碼都是admin
4:運行nginx容器
# docker stop docker-registry-proxy docker-registry-proxy # docker run -d -p 443:443 --name docker-registry-proxy-ip -e REGISTRY_HOST="docker-registry" -e REGISTRY_PORT="5000" -e SERVER_NAME="hh.registry.com" --link docker-registry:docker-registry -v /opt/docker/registry/conf_ip/docker-registry.htpasswd:/etc/nginx/.htpasswd:ro -v /opt/docker/registry/conf_ip:/etc/nginx/ssl:ro containersol/docker-registry-proxy
搭建好registry私有倉庫後,在需要訪問該私倉的客戶端docker宿主機上,無需修改/etc/hosts文件,直接將registry主機上的證書,復制成客戶端docker宿主機上的/etc/docker/certs.d/192.168.1.104/ca.crt文件。
客戶端docker宿主機配置好以後,驗證步驟如下:
# curl -X GET https://admin:[email protected]/v2/_catalog -k {"repositories":["hello-world","redis","ubuntu"]}
# docker login -u admin -p admin -e a 192.168.1.104 WARNING: login credentials saved in /root/.docker/config.json Login Succeeded
# docker pull 192.168.1.104/redis Using default tag: latest latest: Pulling from redis 80ab95908a2b: Pull complete a3ed95caeb02: Pull complete 47a0d79f89b9: Pull complete 7190081b1686: Pull complete fe09c22d81ac: Pull complete a5eae2bcc645: Pull complete 662723161f77: Pull complete b568670a8ccd: Pull complete a1a961e320bc: Pull complete Digest: sha256:769ac80a4711258ec4d6d325f3ad31fbce3bbfa006d5f8aae94c94917dfb0384 Status: Downloaded newer image for 192.168.1.104/redis:latest
參考:
https://docs.docker.com/registry/
https://hub.docker.com/r/chalimartines/cdh5-pseudo-distributed/
http://www.pangxie.space/docker/353
https://docs.docker.com/registry/insecure/
http://www.tianmaying.com/tutorial/docker-registry
搭建docker私有倉庫