03搭建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:
[[email protected] /]# systemctl daemon-reload
[[email protected] /]# 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 -e a 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