1. 程式人生 > >03搭建docker私有倉庫

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