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


原文地址

在部署 registry 之前需要現在主機上安裝 Docker。registry 實際上就是運行在 Docker 中的 registry 鏡像的實例。

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

如果你有 air-gapped 數據中心,參考 air-gapped registries 的注意事項

1. 運行本地 registry

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

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

registry 現在可以使用了。

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

2. 從 Docker Hub 復制鏡像到 registry

可以從 Docker Hub 中提取鏡像並將其推送到你的 registry。以下示例從 Docker Hub 中取出 ubuntu:16.04 鏡像,並將其重新標記為 my-ubuntu,然后將其放入本地 registry。最后,刪除本地的 ubuntu:16.04my-ubuntu 鏡像,並從本地 registry 中取出 my-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 鏡像。

$ 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,並確保你符合包含重新分配不可分配構件的任何條款。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM