寫在前面:
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 localhost:5000/my-ubuntu
注意,此處必須指明
<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服務器在海外)。建議使用國內鏡像加速。參考Docker 中國官方鏡像加速
終止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"
然後,重啓registry。
可以參考以下兩篇博文:
docker registry 鏡像刪除
誰用光了磁盤?Docker System命令詳解
核心命令是:
查詢鏡像信息:
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