Docker 開源項目之 registry - 部署 registry (註冊表)服務器

原文地址node

在部署 registry 以前須要如今主機上安裝 Docker。registry 實際上就是運行在 Docker 中的 registry 鏡像的實例。linux

本主題提供關於部署和配置 registry 的基本信息。要查看配置選項列表,請參考 配置手冊web

若是你有 air-gapped 數據中心,參考 air-gapped registries 的注意事項redis

1. 運行本地 registry

使用下面命令來啓動 registry 容器:sql

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

registry 如今可使用了。docker

警告:前幾個示例顯示的 registry 配置僅適用於測試環境。生產環境的 registry 必須受 TLS 保護,而且應該使用訪問控制機制。繼續閱讀下一篇 registry 配置指南 以在生產環境中部署 registry。json

2. 從 Docker Hub 複製鏡像到 registry

能夠從 Docker Hub 中提取鏡像並將其推送到你的 registry。如下示例從 Docker Hub 中取出 ubuntu:16.04 鏡像,並將其從新標記爲 my-ubuntu,而後將其放入本地 registry。最後,刪除本地的 ubuntu:16.04my-ubuntu 鏡像,並從本地 registry 中取出 my-ubuntu 鏡像。ubuntu

1. 從 Docker Hub 中取出 ubuntu:16.04 鏡像

$ docker pull ubuntu:16.04
   
   
   

  

2. 爲鏡像添加標籤 localhost:5000/my-ubuntu。這會會已經存在的鏡像建立附加標籤。標籤第一部分是主機名和端口號,執行 push 操做時 Docker 將其解析爲 registry 的位置。

$ docker tag ubuntu:16.04 localhost:5000/my-ubuntu
   
   
   

  

3. 上傳鏡像到運行在 localhost:5000 的本地 registry:

$ docker push localhost:5000/my-ubuntu
   
   
   

  

4. 刪除本地緩存中的 ubuntu:16.04my-ubuntu 鏡像

刪除後,能夠測試從你的本地 registry 中獲取鏡像。這不會刪除你的 registry 中的 localhost:5000/my-ubuntu 鏡像。windows

$ docker image remove ubuntu:16.04
$ docker image remove localhost:5000/my-ubuntu
   
   
   

  

5. 從你的本地 registry 中獲取 localhost:5000/my-ubuntu 鏡像

$ docker pull localhost:5000/my-ubuntu
   
   
   

  

3. 中止本地 registry

相似中止其餘容器,經過 docker container stop 命令能夠中止本地 registry:後端

$ docker container stop registry
   
   
   

  

經過 docker container rm 命令能夠刪除容器:

$ docker container stop registry && docker container rm -v registry
   
   
   

  

4. 基本配置

要配置容器,能夠將附加選項或修改選項傳遞給 docker run 命令。

下面提供了配置 registry 的基本指導原則。更多詳細信息,請參閱 registry 配置參考

4.1 自動啓動 registry

若是你但願將 registry 用做永久性基礎架構的一部分,則應將其設置爲在 Docker 從新啓動或退出時自動從新啓動。本示例使用 --restart always 標誌爲 registry 設置從新啓動策略。

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

  

4.2 自定義發佈的端口

若是端口 5000 已經被佔用,或者你想運行多個本地 registry 來分隔關注的區域,則能夠自定義 registry 的端口。下面的示例在端口 5001 上運行 registry,並將其命名爲 registry-test。請記住,-p 值的第一部分是主機端口,第二部分是容器內的端口。在容器中,registry 默認在端口 5000 上監聽。

$ docker run -d \
  -p 5001:5000 \   --name registry-test \   registry:2
   
   
   

  

若是要在容器中更改 registry 監聽的端口(If you want to change the port the registry listens on within the container),可使用環境變量 REGISTRY_HTTP_ADDR 來更改它。此命令使 registry 監聽容器內的端口 5001:

$ docker run -d \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:5001 \   -p 5001:5001 \   --name registry-test \   registry:2
   
   
   

  

5. 存儲自定義

5.1 自定義存儲位置

默認狀況下,registry 數據在主機文件系統上做爲 docker卷 持久保存。若是要將 registry 內容存儲在主機文件系統上的特定位置,例如掛載到特定目錄的 SSD 或 SAN ,則可使用綁定掛載。綁定掛載更依賴於 Docker 主機的文件系統佈局,但在許多狀況下性能更高。下面的示例將主機的 /mnt/registry 目錄綁定到 registry 容器的 /var/lib/registry/ 目錄中。

$ docker run -d \
  -p 5000:5000 \   --restart=always \   --name registry \   -v /mnt/registry:/var/lib/registry \   registry:2
   
   
   

  

5.2 自定義存儲後端

默認狀況下,registry 將其數據存儲在本地文件系統中,不管你是使用綁定掛載仍是使用卷。可使用 存儲驅動程序 將 registry 數據存儲在 Amazon S3 bucket,Google Cloud Platform 或其餘存儲後端中。更多信息,請參閱 存儲配置選項

6. 運行可從外部訪問的 registry

運行僅在本地主機上可訪問的 registry 具備有限的用處。爲了使你的 registry 可以被外部主機訪問,必須先開啓 TLS。

下面的示例在下一小節 運行 registry 做爲服務 中進行了擴展。

6.1 獲取證書

這些例子假設以下:

  • 你的註冊網址是 https://myregistry.domain.com/
  • 你的 DNS,路由和防火牆設置容許經過端口 443 訪問 registry 所在主機。
  • 你已經從認證中心(certificate authority,CA)得到證書。

若是你已得到中間證書,請參閱本小節最後一部分 使用中間證書。

1. 建立證書目錄

$ mkdir -p certs
   
   
   

  

.crt.key 文件從 CA 複製到 certs 目錄中。如下步驟假定這些文件被命名爲 domain.crtdomain.key

2. 若是 registry 正在運行,則中止 registry

$ docker container stop registry
   
   
   

  

3. 從新啓動 registry

指示 registry 使用 TLS 證書。該命令將 certs/ 目錄綁定到容器中的 /cert/ 目錄,並設置環境變量來告訴容器在哪裏找到 domain.crtdomain.key 文件。registry 在端口 443 上運行,即默認的 HTTPS 端口。

$ docker run -d \
  --restart=always \   --name registry \   -v `pwd`/certs:/certs \   -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \   -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \   -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \   -p 443:443 \   registry:2
   
   
   

  

4. Docker 客戶端如今可使用外部地址從 registry 中下載上傳鏡像:

$ docker pull ubuntu:16.04
$ docker tag ubuntu:16.04 myregistry.domain.com/my-ubuntu
$ docker push myregistry.domain.com/my-ubuntu
$ docker pull myregistry.domain.com/my-ubuntu
   
   
   

  

使用中間證書

證書頒發者可能會提供中間證書。在這種狀況下,必須將你的證書與中間證書鏈接起來造成一個證書包(certificate bundle)。可使用 cat 命令執行此操做:

cat domain.crt intermediate-certificates.pem > certs/domain.crt
   
   
   

  

就像在前面的示例中使用 domain.crt 文件同樣,可使用 certificate bundle。

6.2 對 Let’s Encrypt 的支持

registry 支持使用 Let’s Encrypt 自動獲取瀏覽器信任的證書。有關 Let’s Encrypt 的更多信息,請參閱 https://letsencrypt.org/how-it-works/registry 配置 的相關部分。

6.3 使用不安全的 registry(僅適合測試環境)

可使用自簽名證書,或者不安全地使用 registry。除非你已爲自簽名證書設置驗證,不然這僅用於測試。請參閱 運行不安全的註冊表

7. Run the registry as a service

Swarm 服務 相對於獨立容器有幾個優點。他們使用聲明式模型(declarative model),這意味着你定義了所需的狀態,而且 Docker 可使你的服務保持在該狀態。服務提供自動負載均衡擴展,以及控制服務分佈的能力等優點。服務還容許你在 secrets 中存儲敏感數據,例如 TLS 證書。

你使用的存儲後端決定你是使用徹底伸縮的服務仍是僅使用單個節點或節點約束的服務。

  • 若是使用分佈式存儲驅動程序(如 Amazon S3),則可使用徹底複製的服務(a fully replicated service)。每一個工做人員均可以寫入存儲後端,而不會致使寫入衝突。
  • 若是使用本地綁定掛載或卷,則每一個工做節點都會寫入其本身的存儲位置,這意味着每一個 registry 都包含一個不一樣的數據集。能夠經過使用單副本服務(single-replica service)和節點約束來解決此問題,以確保只有一個工做節點正在寫入綁定掛載。

如下示例將 registry 做爲單副本服務啓動,該服務可經過任何 swarm 節點的 80 端口訪問。假定你使用的是與前面示例中相同的 TLS 證書。

首先,將 TLS 證書和密鑰保存爲 secrets:

$ docker secret create domain.crt certs/domain.crt $ docker secret create domain.key certs/domain.key
   
   
   

  

接下來,將標籤添加到要運行 registry 的節點。可使用 docker node ls 獲取節點的名稱。用下面的 node1 替換節點的名稱。

$ docker node update --label-add registry=true node1
   
   
   

  

而後建立服務,授予其訪問這兩個 secrets 的權限,並將其限制爲僅在具備標籤 registry=true 的節點上運行。除了約束以外,還指定一次只能運行一個副本。該示例將 swarm 節點上的 /mnt/registry 綁定掛載到容器中的 /var/lib/registry/。綁定掛載依賴於預先存在的源目錄,所以確保 node1 上存在 /mnt/registry。在運行如下 docker service create 命令以前,可能須要建立它。

默認狀況下,secrets 在 /run/secrets/<secret-name> 處掛載到服務中。

$ docker service create \
  --name registry \   --secret domain.crt \   --secret domain.key \   --constraint 'node.labels.registry==true' \   --mount type=bind,src=/mnt/registry,dst=/var/lib/registry \   -e REGISTRY_HTTP_ADDR=0.0.0.0:80 \   -e REGISTRY_HTTP_TLS_CERTIFICATE=/run/secrets/domain.crt \   -e REGISTRY_HTTP_TLS_KEY=/run/secrets/domain.key \   --publish published=80,target=80 \   --replicas 1 \   registry:2
   
   
   

  

能夠訪問任何 swarm 節點的 80 端口上的服務。Docker 將請求發送到正在運行該服務的節點。

8. 負載均衡的考慮

人們可能想要使用負載均衡器分配負載,終止 TLS 或提供高可用性。雖然完整的負載均衡設置不在本文檔的範圍內,但有一些注意事項可使該過程更加流暢。

最重要的方面是,負載均衡的 registry 集羣必須共享相同的資源。對於當前版本的 registry,這意味着如下內容必須相同:

  • 存儲驅動程序
  • HTTP Secret
  • Redis 緩存(若是已配置)

上述任何差別都會致使服務請求出現問題。例如,若是使用的是文件系統驅動程序,則全部 registry 實例都必須可以訪問同一臺計算機上的相同文件系統根目錄。對於其餘驅動程序(如 S3 或 Azure),它們應該訪問相同的資源並共享相同的配置。HTTP Secret 協調上傳(The HTTP Secret coordinates uploads),跨實例也必須相同。能夠配置不一樣的 redis 實例(編寫本文時),但若是實例不共享,則不是最優的,由於此時會致使更多的請求發送到後端服務器而不是使用 redis 緩存。

8.1 重要/必需的 HTTP 頭

正確獲取 header 很是重要。對於「/v2/」地址空間下的任何請求的全部響應,即便是 4xx 響應,Docker-Distribution-API-Version 的 header 也應設置爲值「registry/2.0」。若是須要,此頭容許 docker 引擎快速解析身份驗證提示信息並回退到版本 1 的registry。確認此設置是否正確能夠幫助避免回退問題。(This header allows the docker engine to quickly resolve authentication realms and fallback to version 1 registries, if necessary. Confirming this is setup correctly can help avoid problems with fallback.)

在一樣的思路中,你必須確保正確地將 X-Forwarded-ProtoX-Forwarded-ForHost header 發送到它們的「客戶端」值。若是不這樣作,一般會使 registry 問題重定向到內部主機名或從 https 降級到 http。(Failure to do so usually makes the registry issue redirects to internal hostnames or downgrading from https to http.)

當「/v2/」端點在沒有憑證的狀況下被訪問時,正確安全的 registry 應返回 401。響應應包含 WWW-Authenticate,爲如何進行身份驗證提供指導,例如使用基自己份驗證或令牌服務。若是負載平衡器有健康檢查,建議將其配置爲將 401 響應視爲健康情況,其餘狀況視爲關閉。經過確保認證的配置問題不會意外暴露未受保護的 registry,能夠確保安全。若是你使用的是不太複雜的負載平衡器(例如亞馬遜的 Elastic Load Balancer),它不容許更改健康的響應代碼,則健康檢查能夠定向到「/」,它老是返回 200 OK 響應。

9. 限制訪問

除了在安全的本地網絡上運行的 registry 外,應始終對 registry 實施訪問限制。

9.1 原生基自己份驗證 native basic authentication

實現訪問限制的最簡單方法是經過基本認證(相似於其餘 Web 服務器的基本認證機制)。這個例子使用經過 htpasswd 來存儲 secrets 的原生基自己份認證。

警告:沒法使用以純文本格式發送憑證的身份驗證方案進行身份驗證。必須首先配置 TLS 才能使驗證生效。

1. 爲用戶 testuser 建立一個包含密碼 testpassword 的密碼文件:

$ mkdir auth
$ docker run \
  --entrypoint htpasswd \
  registry:2 -Bbn testuser testpassword > auth/htpasswd
   
   
   

  

2. 中止 registry

$ docker container stop registry
   
   
   

  

3. 使用基自己份驗證啓動 registry

$ docker run -d \
  -p 5000:5000 \   --restart=always \   --name registry \   -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
   
   
   

  

4. 嘗試從 registry 獲取鏡像,或上傳鏡像到 registry。這會所有失敗。

5. 登陸 registry

$ docker login myregistrydomain.com:5000
   
   
   

  

在第一步提供用戶名和密碼。

測試如今能夠從 registry 中獲取鏡像或將鏡像推送到 registry。

X509 錯誤:X509 錯誤一般代表你正在嘗試使用自簽名證書,但未正確配置 Docker 守護程序。請參閱 運行不安全的註冊表

9.2 更多高級認證

你可能但願經過在 registry 前使用代理來實現更高級的基自己份驗證。見 recipes 列表。

註冊表還支持委派認證(delegated authentiation),將用戶重定向到特定的可信令牌服務器(token server)。這種方法設置起來更加複雜,只有在須要徹底配置 ACL 並須要更多控制 registry 與全局受權和身份驗證系統的集成時纔有意義(only makes sense if you need to fully configure ACLs and need more control over the registry’s integration into your global authorization and authentication systems)。請參閱如下 背景信息配置信息

這種方法須要你使用本身的或第三方認證系統。

10. 經過 compose 文件部署 registry

若是 registry 很複雜,那麼使用 Docker compose 文件來部署它可能更容易,而不是依賴於特定的 docker run 調用。使用如下示例 docker-compose.yml 做爲模板。

registry:
  restart: always
  image: registry:2
  ports:
    - 5000: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
   
   
   

  

/path 替換爲包含 certs/auth/ 目錄的目錄。

經過在包含 docker-compose.yml 文件的目錄中發出如下命令來啓你的 registry:

$ docker-compose up -d
   
   
   

  

11. 對 air-gapped registry 的考慮

能夠在沒有互聯網鏈接的環境中運行 registry。可是,若是你依賴任何非本地鏡像,則須要考慮如下幾點:

  • 你可能須要在鏈接的主機上構建本地 registry 的數據卷,能夠在其中運行 docker pull 以獲取遠程可用的任何鏡像,而後將 registry 的數據卷遷移到隔離網絡(air-gapped network)。
  • 某些鏡像,如官方 Microsoft Windows 基本鏡像,不可分發。這意味着當你將基於這些鏡像之一的鏡像上傳到你的私人 registry 時,不會推送不可分發的層,而是始終從其受權位置獲取。這對於鏈接互聯網的主機來講很好,但不能用於空隙設置(air-gapped set-up)。

在 Docker 17.06 及更高版本中,能夠配置 Docker 守護程序,以容許在這種狀況下將不可分配的層上傳到私有 registry。這僅適用於存在不可分配鏡像的空隙設置或帶寬極端有限的狀況下。你有責任確保你符合不可分配的層的使用條款。

1. 編輯 Linux 主機上的 /etc/docker/ 和 Windows Server 上的 C:\ProgramData\docker\config\daemon.json 中的 daemon.json 文件。假設文件先前爲空,請添加如下內容:

{
  "allow-nondistributable-artifacts": ["myregistrydomain.com:5000"] }
   
   
   

  

值是 registry 地址數組,用逗號分隔。
保存並退出。

2. 重啓 Docker

3. 若是 registry 沒有自動重啓,則重啓 registry

4. 當你將鏡像上傳到 registry 時,它們的不可分發層也會上傳到 registry。

警告:不可分發的構件一般對如何以及在何處分發和共享有限制。只有使用此功能才能將工件推送到私有 registry,並確保你符合包含從新分配不可分配構件的任何條款。

相關文章
相關標籤/搜索