一路踩坑:Centos7環境下Docker搭建私有registry
寫在前面:
Docker私有registry指的是在私有伺服器上搭建的、用於管理Docker repositories的實體。可以理解成私有的Docker資源管理倉庫。搭建Docker私有registry,本質上是從Docker官方庫拉取registry
映象,並在本地Docker中執行。Docker官方文件介紹了搭建的步驟。但是在實際部署中,會遇到一些文件中沒有詳細描述的情況和問題。這篇博文記錄了部署私有registry並配置https的完整步驟,並且探討了儲存空間不足的一些解決方案。
部署環境
- 作業系統:Centos7
- 已經安裝好Docker CE版
- 可以聯網
基本步驟
在命令列通過以下命令就可以啟動一個本地的registry:
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
該registry執行在localhost的5000埠,使用
http
協議.--restart=always
表示該例項遇到問題會自動重啟,--name registry
表示名字是registry
。可以自己起名。向本地私有registry推送映象
從Docker Hub上拉取一個映象,例如
ubuntu:16.04
:$ docker pull ubuntu:16.04
將此映象tag為
localhost:5000/my-ubuntu
:$ docker tag ubuntu:16.04
注意,此處必須指明
<host:port>
,否則後續會預設push到官方Docker Hub上。將tag的映象推送到本地的私有registry:
$ docker push localhost:5000/my-ubuntu
刪除本地的映象,嘗試從私有registry中拉取:
刪除:$ docker image remove ubuntu:16.04
$ docker image remove localhost:5000/my-ubuntu
拉取:
$ docker pull localhost:5000/my-ubuntu
- 在步驟2中,可能會遇到拉取映象慢的問題(Docker Hub伺服器在海外)。建議使用國內映象加速。參考
終止registry執行
$ docker stop registry
也可以刪除容器:
$ docker stop registry && docker rm -v registry
在部署過程中,如果遇到registry不斷重啟的情況,可以檢視docker執行日誌來診斷問題:
docker logs --tail 50 --follow --timestamps <your_container_name/id>
對registry的執行時配置
registry
本質上也是一個容器,可以使用docker run
命令執行。執行時是使用root
使用者還是普通使用者,取決於安裝時使用的使用者。基本的執行方法,就如上文所述。
自動重啟
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
重點在於
--restart=always
自定義埠號
$ docker run -d -p 5050:5000 --restart=always --name registry-test registry:2
這條指令會在localhost的5050埠啟動一個名為
registry-test
的registry容器。在容器內部,則監聽5000
埠。
可以通過REGISTRY_HTTP_ADDR
命令改變容器內部監聽的埠:$ docker run -d -e REGISTRY_HTTP_ADDR=0.0.0.0:5001 -p 5050:5001 --name registry-test registry:2
這樣在容器內部,會監聽
5001
埠。自定義本地儲存路徑
$ docker run -d -p 5000:5000 --restart=always --name registry -v /mnt/registry:/var/lib/registry registry:2`
該指令將registry內部的
/var/lib/registry
對映到本機的/mnt/registry
路徑,推送到該registry的映象就會都儲存在本地的/mnt/registry
路徑下。
搭建可外部訪問的registry (https)
上文所描述的步驟,是用於在本地搭建一個私有registry. 如果需要搭建外部可訪問的registry,需要有https的證書,然後使用域名訪問你的私有registry.
假設域名為reg.example.org
。
先建立一個certs
路徑:
$ mkdir -p certs
如果你已經有自己的證書,將你的.crt
和.key
檔案直接拷貝到certs
路徑。
如果使用的是intermediate證書,需要做如下處理:
- 若你有
.crt
和.pem
檔案:
cat domain.crt intermediate-certificates.pem > certs/domain.crt
- 若你有
.crt
和IntermediateCA.crt
檔案(我是這種情況):
cat ssl_certificate.crt IntermediateCA.crt > certs/domain.crt
注意:必須先放自己的ssl證書,再拼接intermediaCA,否則會由於證書錯誤導致registry不斷重啟、不能提供服務。
使用如下指令啟動registry:
docker run -d --restart=always --name testreg \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:80 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
-p 80:80 \
registry:2
我在80
埠啟動了registry. 因此所有要push到這個registry的映象,都需要在打tag的時候指明域名和ip:reg.example.org:80/my-ubuntu
。如果tag中沒有指明埠號,則docker會預設使用443埠(https的埠號)。如果你的私有registry剛好指定執行在443埠上,則ok沒問題;如果不是在443埠,就會報錯訪問被拒絕。
通過使用者管理控制訪問許可權
可以通過docker指令建立使用者,以限制訪問許可權。
建立使用者:
$ mkdir auth
$ docker run \
--entrypoint htpasswd \
registry:2 -Bbn testuser testpassword > auth/htpasswd
使用者名稱是testuser
,密碼是testpassword
。
終止registry,以新的引數重新啟動:
$ docker stop testreg
$ docker run -d \
--restart=always \
--name testreg \
-p 80:5000 \
-v `pwd`/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v `pwd`/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
這時,再嘗試push或pull,就會失敗,因為需要登入:
$ docker login reg.example.org:80
通過compose檔案啟動
可以為registry建立docker-compose.yml檔案,便於啟動。大概長這樣:
registry:
restart: always
image: registry:2
ports:
- 80:5000
environment:
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
REGISTRY_HTTP_TLS_KEY: /certs/domain.key
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
volumes:
- /path/data:/var/lib/registry
- /path/certs:/certs
- /path/auth:/auth
關於本地儲存空間不夠的問題
經常性地提交新的docker映象,會佔用registry伺服器大量的空間。為了解決這個問題,需要在docker-compose.yml
檔案中,增加以下環境變數的配置:
REGISTRY_STORAGE_DELETE_ENABLED: "yes"
核心命令是:
查詢映象資訊:
curl --header "Accept: application/vnd.docker.distribution.manifest.v2+json" -I -X GET <protocol>://<registry_host>/v2/<repo_name>/manifests/<tag>
刪除映象:
curl -I -X DELETE <protocol>://<registry_host>/v2/<repo_name>/manifests/<digest_hash>
刪除檔案系統內的映象:
docker exec -it <registry_container_id> bin/registry garbage-collect /etc/docker/registry/config.yml
注意:
1. 要先修改config.yml
。我是在/
目錄下find的。好像啟動的時候可以指定位置。
2. 在centos中,config.yml
的位置,就是/etc/docker/registry/config.yml