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

搭建docker私有倉庫

str tutorial login text author 數據保存 標簽 -a let

搭建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私有倉庫