一路踩坑:Centos7環境下Docker搭建私有registry

寫在前面:

Docker私有registry指的是在私有服務器上搭建的、用於管理Docker repositories的實體。可以理解成私有的Docker資源管理倉庫。搭建Docker私有registry,本質上是從Docker官方庫拉取registry鏡像,並在本地Docker中運行。Docker官方文檔介紹了搭建的步驟。但是在實際部署中,會遇到一些文檔中沒有詳細描述的情況和問題。這篇博文記錄了部署私有registry並配置https的完整步驟,並且探討了存儲空間不足的一些解決方案。

部署環境

  • 操作系統:Centos7
  • 已經安裝好Docker CE版
  • 可以聯網

基本步驟

  1. 在命令行通過以下命令就可以啓動一個本地的registry:

    $ docker run -d -p 5000:5000 --restart=always --name registry registry:2

    該registry運行在localhost的5000端口,使用http協議. --restart=always表示該實例遇到問題會自動重啓,--name registry表示名字是registry。可以自己起名。

  2. 向本地私有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
  3. 在步驟2中,可能會遇到拉取鏡像慢的問題(Docker Hub服務器在海外)。建議使用國內鏡像加速。參考Docker 中國官方鏡像加速
  4. 終止registry運行

    $ docker stop registry

    也可以刪除容器:

    $ docker stop registry && docker rm -v registry
  5. 在部署過程中,如果遇到registry不斷重啓的情況,可以查看docker運行日誌來診斷問題:

    docker logs --tail 50 --follow --timestamps <your_container_name/id>

對registry的運行時配置

registry本質上也是一個容器,可以使用docker run命令運行。運行時是使用root用戶還是普通用戶,取決於安裝時使用的用戶。基本的運行方法,就如上文所述。

  1. 自動重啓

    $ docker run -d -p 5000:5000 --restart=always --name registry registry:2

    重點在於--restart=always

  2. 自定義端口號

    $ 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端口。

  3. 自定義本地存儲路徑

    $ 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
  • 若你有.crtIntermediateCA.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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章