1. 理解Registry
一個registry是一個存儲和內容交付系統,其中維護着若干命名的Docker鏡像,這些鏡像有不同的標記版本。(例如:有一個鏡像名字叫 hello/world,它有兩個tags分別是2.0和2.1)
用戶通過使用 docker push 和 docker pull 命令與 registry 進行交互。(例如:docker pull registry-1.docker.io/hello/world:2.1)
A registry is a storage and content delivery system, holding named Docker images, available in different tagged versions.
Users interact with a registry by using docker push and pull commands.
前面說了,registry是一個存儲系統,它存儲的是Docker鏡像。那么,鏡像到底存到哪里呢?存儲本身委托給驅動程序。默認的存儲驅動程序是本地posix文件系統,還支持其它基於雲的存儲驅動程序,例如 Aliyun OSS
由於保護對托管映像的訪問至關重要,因此Registry本身支持TLS和基本身份驗證。
1.1. 理解鏡像命名
docker pull ubuntu 指示docker從官方Docker Hub中拉取一個名字叫ubuntu的鏡像。這條命令其實是docker pull docker.io/library/ubuntu的簡寫
docker pull myregistrydomain:port/foo/bar 指示docker拉取位於myregistrydomain:port的鏡像foo/bar
1.2. 用例
運行你自己的Registry是與CI/CD系統集成並對其進行補充的絕佳解決方案。在典型的工作流程中,對源版本控制系統的提交將觸發在CI系統上的構建,如果構建成功,則將新鏡像推送到你的Registry。然后,來自Registry的通知將觸發在暫存環境上的部署,或者通知其它系統有一個新鏡像可用。
如果要在大型計算機集群上快速部署新鏡像,它也是必不可少的組件。
這也是在隔離的網絡中分發鏡像的最佳方法。
2. 部署一個registry server
# Run a local registry
docker run -d -p --restart=always --name registry registry:2
2.1. Copy an image from Docker Hub to your registry
你可以從Docker Hub上拉取一個鏡像,並把它推送到你自己的Registry上。下面的例子中,從Docker Hub上拉取鏡像ubuntu:16.04,並將其重新打標記為my-ubuntu,然后將其推送到本地registry,最后,再將ubuntu:16.04和my-ubuntu刪除。
# 1. Pull the ubuntu:16.04 image from Docker Hub
docker pull ubuntu:16.04
# 2. Tag the image as localhost:5000/my-ubuntu
# (注意,當tag的第一部分是主機名和端口時,push時Docker會將其解釋為registry的位置)
docker tag ubuntu:16.04 localhost:5000/my-ubuntu
# 3. Push the image to the local registry running at localhost:5000
docker push localhost:5000/my-ubuntu
# 4. Remove the locally-cached ubuntu:16.04 and localhost:5000/my-ubuntu images, so that you can test pulling the image from your registry. This does not remove the localhost:5000/my-ubuntu image from your registry.
docker image remove ubuntu:16.04
docker image remove localhost:5000/my-ubuntu
# 5. Pull the localhost:5000/my-ubuntu image from your local registry
docker pull localhost:5000/my-ubuntu
停止本地registry
# stop the registry
docker container stop registry
# remove the container
docker container stop registry && docker container rm -v registry
3. 基本配置
為了配置container,可以給docker run命令指定額外的選項參數
# 自動重啟registry
# -p選項的值,第一個是主機端口,第二個是容器端口。在容器中,registry默認監聽端口是5000
docker run -d -p 5000:5000 --restart=always --name registry registry:2
# 自定義存儲位置
docker run -d -p 5000:5000 --restart=always --name registry -v /mnt/registry:/var/lib/registry registry:2
3.1. 運行一個外部可訪問的registry
運行一個僅在本地主機上可訪問的registry沒有什么用處,為了使你的registry可供外部主機訪問,必須首先使用TLS保護registry。
下面是一個將registry作為服務來運行的例子:
首先,獲得一個證書
假設你的registry的URL是https://myregistry.domain.com/,同時假設的DNS,路由和防火牆設置允許通過端口443訪問registry的主機,再假設你已經從CA那里獲得一個證書。
那么,接下來
創建一個certs目錄
從CA那里復制.crt和.key文件到certs目錄,假設分別重命名為domain.crt和domain.key
重啟registry,將其指向使用TLS證書
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
現在Docker客戶端就可以通過registry的外網地址進行pull和push了
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
將registry作為一個服務運行
與獨立容器相比,swarm services具有多個優點。它們使用聲明式模型,這意味着你定義了所需的狀態,而Docker則將服務保持在該狀態。服務提供了自動負載平衡擴展,並具有控制服務分配的能力以及其他優勢。服務還允許你秘密存儲敏感數據,例如TLS證書。
下面這個例子將registry作為單副本服務啟動,可以在端口80上的任何群集節點上訪問該registry,並假定使用的是與前面示例相同的TLS證書。
# 首先,保存TLS證書和key作為secret
docker secret create domain.crt certs/domain.crt
docker secret create domain.key certs/domain.key
# 接下來,將你想要在上面允許registry的node添加一個標簽
docker node update --label-add registry=true node1
# 再接着,創建一個服務,並授權它可以訪問兩個secret,並將其限制為僅在標簽為registry=true的節點上運行
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:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/run/secrets/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/run/secrets/domain.key \
--publish published=443,target=443 \
--replicas 1 \
registry:2
現在你可以在任何swarm節點的443端口上訪問服務。Docker會將請求發送到運行該服務的節點。
4. 文檔
# 啟動registry
docker run -d -p 5000:5000 --name registry registry:2
# 從Docker Hub上拉取鏡像
docker pull ubuntu
# 給鏡像打tag
docker image tag ubuntu localhost:5000/myfirstimage
# 推送至你自己的registry
docker push localhost:5000/myfirstimage
# 再次從你自己的registry拉取鏡像
docker pull localhost:5000/myfirstimage
# 停止registry並刪除所有數據
docker container stop registry && docker container rm -v registry