1. 程式人生 > >一路踩坑:Centos7環境下Docker搭建私有registry

一路踩坑: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"

核心命令是:

查詢映象資訊:

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