如何使用 Azure Container Registry 工作來取用和維護公用內容
本文提供 Azure Container Registry 的工作流程樣本,可協助您管理公用內容的取用和維護狀況:
- 匯入相依公用映像的本機複本。
- 透過安全性掃描和功能測試來驗證公用映像。
- 將映像升階至私人登錄以供內部使用。
- 針對與公用內容相依的應用程式,觸發基礎映像更新。
- 使用 Azure Container Registry 工作將此工作流程自動化。
下圖為此工作流程的摘要說明:
閘道匯入工作流程可協助您管理外部受控成品上的組織相依性。例如,來源為公用登錄的映像,包括 Docker Hub、GCR、Quay、GitHub Container Registry、Microsoft Container Registry,甚至是其他 Azure 容器登錄。
如需了解公用內容相依性所引發的風險背景資訊,以及如何使用 Azure Container Registry 來降低風險,請參閱 OCI 取用公用內容部落格文章及使用 Azure Container Registry 管理公用內容。
您可以使用 Azure Cloud Shell 或安裝在本機的 Azure CLI 來完成此逐步解說。 建議使用 Azure CLI 2.10 版或更新版本。 如果您需要安裝或升級,請參閱安裝 Azure CLI。
案例概觀
本逐步解說將設定:
- 三個容器登錄,代表:
- 模擬 Docker Hub (
publicregistry
) 以支援變更基礎映像 - 小組登錄 (
contoso
) 以共用私人映像 - 已匯入公用內容的公司/小組共用登錄 (
baseartifacts
)
- 模擬 Docker Hub (
- 每個登錄中的 ACR 工作。 工作:
- 建置模擬公用
node
映像 - 將
node
映像匯入至公司/小組共用登錄並加以驗證 - 建置和部署
hello-world
映像
- 建置模擬公用
- ACR 工作定義,包括下列項目的設定:
- 登錄認證集合,即金鑰保存庫的指標
- 祕密集合,可在
acr-task.yaml
內取得,且為金鑰保存庫的指標 - 已設定值的集合,可在
acr-task.yaml
內使用
- 可保護所有祕密的 Azure 金鑰保存庫
- 可裝載
hello-world
建置應用程式的 Azure 容器執行個體
必要條件
下列步驟將設定逐步解說中所建立及使用的資源值。
設定環境變數
設定環境專屬的變數。 我們會遵循最佳做法,將含永久性內容的資源放在專屬的資源群組中,以盡可能減少意外刪除的情況。 但若有需要,您可以將這些變數放在單一資源群組中。
本文中的範例會針對 Bash 殼層進行格式化。
# Set the three registry names, must be globally unique:
REGISTRY_PUBLIC=publicregistry
REGISTRY_BASE_ARTIFACTS=contosobaseartifacts
REGISTRY=contoso
# set the location all resources will be created in:
RESOURCE_GROUP_LOCATION=eastus
# default resource groups
REGISTRY_PUBLIC_RG=${REGISTRY_PUBLIC}-rg
REGISTRY_BASE_ARTIFACTS_RG=${REGISTRY_BASE_ARTIFACTS}-rg
REGISTRY_RG=${REGISTRY}-rg
# fully qualified registry urls
REGISTRY_DOCKERHUB_URL=docker.io
REGISTRY_PUBLIC_URL=${REGISTRY_PUBLIC}.azurecr.io
REGISTRY_BASE_ARTIFACTS_URL=${REGISTRY_BASE_ARTIFACTS}.azurecr.io
REGISTRY_URL=${REGISTRY}.azurecr.io
# Azure key vault for storing secrets, name must be globally unique
AKV=acr-task-credentials
AKV_RG=${AKV}-rg
# ACI for hosting the deployed application
ACI=hello-world-aci
ACI_RG=${ACI}-rg
Git 存放庫和權杖
若要模擬您的環境,請將下列每個 Git 存放庫的建立派生至您可以管理的存放庫。
- https://github.com/importing-public-content/base-image-node.git
- https://github.com/importing-public-content/import-baseimage-node.git
- https://github.com/importing-public-content/hello-world.git
然後,更新派生存放庫的下列變數。
附加至 git URL 結尾的 :main
代表預設存放庫分支。
GIT_BASE_IMAGE_NODE=https://github.com/<your-fork>/base-image-node.git#main
GIT_NODE_IMPORT=https://github.com/<your-fork>/import-baseimage-node.git#main
GIT_HELLO_WORLD=https://github.com/<your-fork>/hello-world.git#main
您需要 GitHub 存取權杖 (PAT),才能讓 ACR 工作複製及建立 Git Webhook。 如需了解建立含私人存放庫所需權限的權杖步驟,請參閱建立 GitHub 存取權杖。
GIT_TOKEN=<set-git-token-here>
Docker Hub 認證
若要迴避從 Docker Hub 提取映像時的節流和身分識別要求,請建立 Docker Hub 權杖。 接下來,請設定下列環境變數:
REGISTRY_DOCKERHUB_USER=<yourusername>
REGISTRY_DOCKERHUB_PASSWORD=<yourtoken>
建立登錄
使用 Azure CLI 命令來建立三個進階層容器登錄,且每個容器登錄都有自己的資源群組:
az group create --name $REGISTRY_PUBLIC_RG --location $RESOURCE_GROUP_LOCATION
az acr create --resource-group $REGISTRY_PUBLIC_RG --name $REGISTRY_PUBLIC --sku Premium
az group create --name $REGISTRY_BASE_ARTIFACTS_RG --location $RESOURCE_GROUP_LOCATION
az acr create --resource-group $REGISTRY_BASE_ARTIFACTS_RG --name $REGISTRY_BASE_ARTIFACTS --sku Premium
az group create --name $REGISTRY_RG --location $RESOURCE_GROUP_LOCATION
az acr create --resource-group $REGISTRY_RG --name $REGISTRY --sku Premium
建立金鑰保存庫並設定祕密
建立金鑰保存庫:
az group create --name $AKV_RG --location $RESOURCE_GROUP_LOCATION
az keyvault create --resource-group $AKV_RG --name $AKV
在金鑰保存庫中設定 Docker Hub 使用者名稱和權杖:
az keyvault secret set \
--vault-name $AKV \
--name registry-dockerhub-user \
--value $REGISTRY_DOCKERHUB_USER
az keyvault secret set \
--vault-name $AKV \
--name registry-dockerhub-password \
--value $REGISTRY_DOCKERHUB_PASSWORD
在金鑰保存庫中設定並驗證 Git PAT:
az keyvault secret set --vault-name $AKV --name github-token --value $GIT_TOKEN
az keyvault secret show --vault-name $AKV --name github-token --query value -o tsv
建立 Azure 容器執行個體的資源群組
部署 hello-world
映像時,此資源群組會在稍後的工作中使用。
az group create --name $ACI_RG --location $RESOURCE_GROUP_LOCATION
建立公用 node
基礎映像
若要模擬 Docker Hub 上的 node
映像,請建立 ACR 工作以建置和維護公用映像。 此設定允許使用 node
映像維護程式來模擬變更。
az acr task create \
--name node-public \
-r $REGISTRY_PUBLIC \
-f acr-task.yaml \
--context $GIT_BASE_IMAGE_NODE \
--git-access-token $(az keyvault secret show \
--vault-name $AKV \
--name github-token \
--query value -o tsv) \
--set REGISTRY_FROM_URL=${REGISTRY_DOCKERHUB_URL}/ \
--assign-identity
若要迴避 Docker 節流,請將 Docker Hub 認證新增至工作。 acr 工作認證命令可用來將 Docker 認證傳遞至任何登錄,包括 Docker Hub。
az acr task credential add \
-n node-public \
-r $REGISTRY_PUBLIC \
--login-server $REGISTRY_DOCKERHUB_URL \
-u https://${AKV}.vault.azure.net/secrets/registry-dockerhub-user \
-p https://${AKV}.vault.azure.net/secrets/registry-dockerhub-password \
--use-identity [system]
從金鑰保存庫授與工作讀取值的權限:
az keyvault set-policy \
--name $AKV \
--resource-group $AKV_RG \
--object-id $(az acr task show \
--name node-public \
--registry $REGISTRY_PUBLIC \
--query identity.principalId --output tsv) \
--secret-permissions get
觸發工作的方法包括 Git 認可、基礎映像更新、計時器或手動執行。
手動執行工作以產生 node
映像:
az acr task run -r $REGISTRY_PUBLIC -n node-public
列出模擬公用登錄中的映像:
az acr repository show-tags -n $REGISTRY_PUBLIC --repository node
建立 hello-world
映像
根據模擬的公用 node
映像來建置 hello-world
映像。
建立權杖以取得模擬公用登錄的提取權
建立模擬公用登錄的存取權杖,範圍則設為 pull
。 然後在金鑰保存庫中加以設定:
az keyvault secret set \
--vault-name $AKV \
--name "registry-${REGISTRY_PUBLIC}-user" \
--value "registry-${REGISTRY_PUBLIC}-user"
az keyvault secret set \
--vault-name $AKV \
--name "registry-${REGISTRY_PUBLIC}-password" \
--value $(az acr token create \
--name "registry-${REGISTRY_PUBLIC}-user" \
--registry $REGISTRY_PUBLIC \
--scope-map _repositories_pull \
-o tsv \
--query credentials.passwords[0].value)
透過 Azure 容器執行個體建立提取權的權杖
建立裝載 hello-world
映像的登錄存取權杖,範圍則設為提取。 然後在金鑰保存庫中加以設定:
az keyvault secret set \
--vault-name $AKV \
--name "registry-${REGISTRY}-user" \
--value "registry-${REGISTRY}-user"
az keyvault secret set \
--vault-name $AKV \
--name "registry-${REGISTRY}-password" \
--value $(az acr token create \
--name "registry-${REGISTRY}-user" \
--registry $REGISTRY \
--repository hello-world content/read \
-o tsv \
--query credentials.passwords[0].value)
建立工作以建置和維護 hello-world
映像
下列命令會透過 hello-world
存放庫 acr-tasks.yaml
中的定義來建立工作。 工作步驟會建置 hello-world
映像,然後將其部署至 Azure 容器執行個體。 Azure 容器執行個體的資源群組已於上一節建立。 藉由在工作中呼叫 az container create
,且只有 image:tag
處有差異,工作就可在整個逐步解說流程中部署到相同的執行個體。
az acr task create \
-n hello-world \
-r $REGISTRY \
-f acr-task.yaml \
--context $GIT_HELLO_WORLD \
--git-access-token $(az keyvault secret show \
--vault-name $AKV \
--name github-token \
--query value -o tsv) \
--set REGISTRY_FROM_URL=${REGISTRY_PUBLIC_URL}/ \
--set KEYVAULT=$AKV \
--set ACI=$ACI \
--set ACI_RG=$ACI_RG \
--assign-identity
將認證新增至模擬公用登錄的工作:
az acr task credential add \
-n hello-world \
-r $REGISTRY \
--login-server $REGISTRY_PUBLIC_URL \
-u https://${AKV}.vault.azure.net/secrets/registry-${REGISTRY_PUBLIC}-user \
-p https://${AKV}.vault.azure.net/secrets/registry-${REGISTRY_PUBLIC}-password \
--use-identity [system]
從金鑰保存庫授與工作讀取值的權限:
az keyvault set-policy \
--name $AKV \
--resource-group $AKV_RG \
--object-id $(az acr task show \
--name hello-world \
--registry $REGISTRY \
--query identity.principalId --output tsv) \
--secret-permissions get
透過授與資源群組存取權,即可授與工作存取權,以建立和管理 Azure 容器執行個體:
az role assignment create \
--assignee $(az acr task show \
--name hello-world \
--registry $REGISTRY \
--query identity.principalId --output tsv) \
--scope $(az group show -n $ACI_RG --query id -o tsv) \
--role owner
建立並設定工作後,請執行工作以建置和部署 hello-world
映像:
az acr task run -r $REGISTRY -n hello-world
建立後,請取得裝載 hello-world
映像的容器 IP 位址。
az container show \
--resource-group $ACI_RG \
--name ${ACI} \
--query ipAddress.ip \
--out tsv
請在瀏覽器中前往 IP 位址查看執行中的應用程式。
使用「有問題」變更來更新基礎映像
本節將模擬可能會造成環境問題的基礎映像變更。
- 在派生的
base-image-node
存放庫中開啟Dockerfile
。 - 將
BACKGROUND_COLOR
變更為Orange
以模擬變更。
ARG REGISTRY_NAME=
FROM ${REGISTRY_NAME}node:15-alpine
ENV NODE_VERSION 15-alpine
ENV BACKGROUND_COLOR Orange
認可變更並監看 ACR 工作以自動開始建置。
監看開始執行的工作:
watch -n1 az acr task list-runs -r $REGISTRY_PUBLIC -o table
根據觸發程序 Commit
,您最終應該會看到狀態 Succeeded
:
RUN ID TASK PLATFORM STATUS TRIGGER STARTED DURATION
-------- -------- ---------- --------- --------- -------------------- ----------
ca4 hub-node linux Succeeded Commit 2020-10-24T05:02:29Z 00:00:22
輸入 Ctrl+C 以結束監看命令,然後檢視最近執行的記錄:
az acr task logs -r $REGISTRY_PUBLIC
node
映像完成後,請針對 ACR 工作執行 watch
,系統會自動開始建置 hello-world
映像:
watch -n1 az acr task list-runs -r $REGISTRY -o table
根據觸發程序 Image Update
,您最終應該會看到狀態 Succeeded
:
RUN ID TASK PLATFORM STATUS TRIGGER STARTED DURATION
-------- ----------- ---------- --------- ------------ -------------------- ----------
dau hello-world linux Succeeded Image Update 2020-10-24T05:08:45Z 00:00:31
輸入 Ctrl+C 以結束監看命令,然後檢視最近執行的記錄:
az acr task logs -r $REGISTRY
完成後,請取得裝載更新 hello-world
映像的網站 IP 位址:
az container show \
--resource-group $ACI_RG \
--name ${ACI} \
--query ipAddress.ip \
--out tsv
在您的瀏覽器中前往網站,該網站的背景應該為橘色 (代表有問題)。
簽入
此時,您已建立在 Git 認可上自動建置,且變更為基礎 node
映像的 hello-world
映像。 在此範例中,工作會針對 Azure Container Registry 中的基礎映像加以建置,但任何支援的登錄也可以使用。
基礎映像更新會在 node
映像更新時,自動重新觸發工作執行。 如這裡所示,並非所有的更新都是需要的。
公用內容的閘道匯入
若要防止上游變更中斷重大工作負載,您可以新增安全性掃描和功能測試。
在本節中,您將建立 ACR 工作以達成下列目標:
- 建置測試映像
- 針對測試映像執行功能測試指令碼
./test.sh
- 如果映像測試成功,請將公用映像匯入 baseimages 登錄
新增自動化測試
實作自動化測試是為了透過閘道控制所有上游內容。 在此範例中,系統會提供 test.sh
以檢查 $BACKGROUND_COLOR
。 如果測試失敗,系統就會傳回 1
的 EXIT_CODE
,這會造成 ACR 工作步驟失敗並結束工作執行。 測試可以任何工具形式展開,包括記錄結果。 閘道是由指令碼中的傳遞/失敗回應所管理,於此處重現:
if [ ""$(echo $BACKGROUND_COLOR | tr '[:lower:]' '[:upper:]') = 'RED' ]; then
echo -e "\e[31mERROR: Invalid Color:\e[0m" ${BACKGROUND_COLOR}
EXIT_CODE=1
else
echo -e "\e[32mValidation Complete - No Known Errors\e[0m"
fi
exit ${EXIT_CODE}
工作 YAML
檢閱 import-baseimage-node
存放庫中的 acr-task.yaml
,其會執行下列步驟:
- 使用下列 Dockerfile 建置測試基礎映像:
ARG REGISTRY_FROM_URL= FROM ${REGISTRY_FROM_URL}node:15-alpine WORKDIR /test COPY ./test.sh . CMD ./test.sh
- 完成後,請執行容器來驗證映像,該容器將執行
./test.sh
- 只有在順利完成時才可執行匯入步驟,其由
when: ['validate-base-image']
透過閘道控制
version: v1.1.0
steps:
- id: build-test-base-image
# Build off the base image we'll track
# Add a test script to do unit test validations
# Note: the test validation image isn't saved to the registry
# but the task logs captures log validation results
build: >
--build-arg REGISTRY_FROM_URL={{.Values.REGISTRY_FROM_URL}}
-f ./Dockerfile
-t {{.Run.Registry}}/node-import:test
.
- id: validate-base-image
# only continues if node-import:test returns a non-zero code
when: ['build-test-base-image']
cmd: "{{.Run.Registry}}/node-import:test"
- id: pull-base-image
# import the public image to base-artifacts
# Override the stable tag,
# and create a unique tag to enable rollback
# to a previously working image
when: ['validate-base-image']
cmd: >
docker pull {{.Values.REGISTRY_FROM_URL}}node:15-alpine
- id: retag-base-image
when: ['pull-base-image']
cmd: docker tag {{.Values.REGISTRY_FROM_URL}}node:15-alpine {{.Run.Registry}}/node:15-alpine
- id: retag-base-image-unique-tag
when: ['pull-base-image']
cmd: docker tag {{.Values.REGISTRY_FROM_URL}}node:15-alpine {{.Run.Registry}}/node:15-alpine-{{.Run.ID}}
- id: push-base-image
when: ['retag-base-image', 'retag-base-image-unique-tag']
push:
- "{{.Run.Registry}}/node:15-alpine"
- "{{.Run.Registry}}/node:15-alpine-{{.Run.ID}}"
建立工作以匯入和測試基礎映像
az acr task create \
--name base-import-node \
-f acr-task.yaml \
-r $REGISTRY_BASE_ARTIFACTS \
--context $GIT_NODE_IMPORT \
--git-access-token $(az keyvault secret show \
--vault-name $AKV \
--name github-token \
--query value -o tsv) \
--set REGISTRY_FROM_URL=${REGISTRY_PUBLIC_URL}/ \
--assign-identity
將認證新增至模擬公用登錄的工作:
az acr task credential add \
-n base-import-node \
-r $REGISTRY_BASE_ARTIFACTS \
--login-server $REGISTRY_PUBLIC_URL \
-u https://${AKV}.vault.azure.net/secrets/registry-${REGISTRY_PUBLIC}-user \
-p https://${AKV}.vault.azure.net/secrets/registry-${REGISTRY_PUBLIC}-password \
--use-identity [system]
從金鑰保存庫授與工作讀取值的權限:
az keyvault set-policy \
--name $AKV \
--resource-group $AKV_RG \
--object-id $(az acr task show \
--name base-import-node \
--registry $REGISTRY_BASE_ARTIFACTS \
--query identity.principalId --output tsv) \
--secret-permissions get
執行匯入工作:
az acr task run -n base-import-node -r $REGISTRY_BASE_ARTIFACTS
注意
如果工作因為 ./test.sh: Permission denied
而失敗,請確定指令碼具有執行權限,並認可回 Git 存放庫:
chmod +x ./test.sh
更新 hello-world
映像即可從閘道 node
映像建置
建立存取權杖即可存取基礎成品登錄,請透過 node
存放庫將範圍設為 read
。 然後,在金鑰保存庫中設定下列內容:
az keyvault secret set \
--vault-name $AKV \
--name "registry-${REGISTRY_BASE_ARTIFACTS}-user" \
--value "registry-${REGISTRY_BASE_ARTIFACTS}-user"
az keyvault secret set \
--vault-name $AKV \
--name "registry-${REGISTRY_BASE_ARTIFACTS}-password" \
--value $(az acr token create \
--name "registry-${REGISTRY_BASE_ARTIFACTS}-user" \
--registry $REGISTRY_BASE_ARTIFACTS \
--repository node content/read \
-o tsv \
--query credentials.passwords[0].value)
將認證新增至基礎成品登錄的 hello-world 工作:
az acr task credential add \
-n hello-world \
-r $REGISTRY \
--login-server $REGISTRY_BASE_ARTIFACTS_URL \
-u https://${AKV}.vault.azure.net/secrets/registry-${REGISTRY_BASE_ARTIFACTS}-user \
-p https://${AKV}.vault.azure.net/secrets/registry-${REGISTRY_BASE_ARTIFACTS}-password \
--use-identity [system]
更新工作即可變更 REGISTRY_FROM_URL
以使用 BASE_ARTIFACTS
登錄
az acr task update \
-n hello-world \
-r $REGISTRY \
--set KEYVAULT=$AKV \
--set REGISTRY_FROM_URL=${REGISTRY_BASE_ARTIFACTS_URL}/ \
--set ACI=$ACI \
--set ACI_RG=$ACI_RG
執行 hello-world 工作來變更其基礎映像相依性:
az acr task run -r $REGISTRY -n hello-world
使用「有效」變更更新基礎映像
- 開啟
base-image-node
存放庫中的Dockerfile
。 - 將
BACKGROUND_COLOR
變更為Green
以模擬有效的變更。
ARG REGISTRY_NAME=
FROM ${REGISTRY_NAME}node:15-alpine
ENV NODE_VERSION 15-alpine
ENV BACKGROUND_COLOR Green
認可變更並監視更新序列:
watch -n1 az acr task list-runs -r $REGISTRY_PUBLIC -o table
執行後,請輸入 Ctrl+C 並監視記錄:
az acr task logs -r $REGISTRY_PUBLIC
完成後,請監視 base-image-import 工作:
watch -n1 az acr task list-runs -r $REGISTRY_BASE_ARTIFACTS -o table
執行後,請輸入 Ctrl+C 並監視記錄:
az acr task logs -r $REGISTRY_BASE_ARTIFACTS
完成後,請監視 hello-world 工作:
watch -n1 az acr task list-runs -r $REGISTRY -o table
執行後,請輸入 Ctrl+C 並監視記錄:
az acr task logs -r $REGISTRY
完成後,請取得裝載更新 hello-world
映像的網站 IP 位址:
az container show \
--resource-group $ACI_RG \
--name ${ACI} \
--query ipAddress.ip \
--out tsv
在您的瀏覽器中前往網站,該網站的背景應該為綠色 (代表有效)。
檢視閘道工作流程
再次執行上一節的步驟,背景為紅色。
- 在存放庫
base-image-node
中開啟Dockerfile
- 將
BACKGROUND_COLOR
變更為Red
以模擬無效的變更。
ARG REGISTRY_NAME=
FROM ${REGISTRY_NAME}node:15-alpine
ENV NODE_VERSION 15-alpine
ENV BACKGROUND_COLOR Red
認可變更並監視更新序列:
watch -n1 az acr task list-runs -r $REGISTRY_PUBLIC -o table
執行後,請輸入 Ctrl+C 並監視記錄:
az acr task logs -r $REGISTRY_PUBLIC
完成後,請監視 base-image-import 工作:
watch -n1 az acr task list-runs -r $REGISTRY_BASE_ARTIFACTS -o table
執行後,請輸入 Ctrl+C 並監視記錄:
az acr task logs -r $REGISTRY_BASE_ARTIFACTS
此時,您應該會看到 base-import-node 工作驗證失敗,並停止序列以發佈 hello-world
更新。 輸出會類似:
[...]
2020/10/30 03:57:39 Launching container with name: validate-base-image
Validating Image
NODE_VERSION: 15-alpine
BACKGROUND_COLOR: Red
ERROR: Invalid Color: Red
2020/10/30 03:57:40 Container failed during run: validate-base-image. No retries remaining.
failed to run step ID: validate-base-image: exit status 1
發佈更新至 hello-world
hello-world
映像的變更將繼續使用最後一個已驗證的 node
映像。
任何通過閘道驗證的基礎 node
映像額外變更,都會觸發 hello-world
映像的基礎映像更新。
清除
如果不再需要本文中使用的資源,請予以刪除。
az group delete -n $REGISTRY_RG --no-wait -y
az group delete -n $REGISTRY_PUBLIC_RG --no-wait -y
az group delete -n $REGISTRY_BASE_ARTIFACTS_RG --no-wait -y
az group delete -n $AKV_RG --no-wait -y
az group delete -n $ACI_RG --no-wait -y
下一步
在本文中,您使用了 ACR 工作來建立自動化閘道工作流程,以將更新的基礎映像引入您的環境。 請參閱相關資訊,了解如何在 Azure Container Registry 中管理映像。