教程:在更新另一个专用 Azure 容器注册表中的基础映像时自动化容器映像生成Tutorial: Automate container image builds when a base image is updated in another private container registry

ACR 任务支持在容器的基础映像更新时自动化映像生成,例如在某个基础映像中修补 OS 或应用程序框架时。ACR Tasks supports automated image builds when a container's base image is updated, such as when you patch the OS or application framework in one of your base images.

本教程介绍在将容器的基础映像推送到另一个 Azure 容器注册表时,如何创建在云中触发生成的 ACR 任务。In this tutorial, you learn how to create an ACR task that triggers a build in the cloud when a container's base image is pushed to another Azure container registry. 你还可以尝试在某篇教程中学习如何创建 ACR 任务,以便在将基本映像推送到同一 Azure 容器注册表时触发映像生成。You can also try a tutorial to create an ACR task that triggers an image build when a base image is pushed to the same Azure container registry.

本教程的内容:In this tutorial:

  • 在基础注册表中生成基础映像Build the base image in a base registry
  • 在另一注册表中创建应用程序生成任务以跟踪基础映像Create an application build task in another registry to track the base image
  • 更新基础映像以触发应用程序映像任务Update the base image to trigger an application image task
  • 显示已触发的任务Display the triggered task
  • 验证已更新的应用程序映像Verify updated application image

备注

在 Azure China 中使用 Azure CLI 2.0 之前,请首先运行 az cloud set -n AzureChinaCloud 更改云环境。Before you can use Azure CLI 2.0 in Azure China, please run az cloud set -n AzureChinaCloud first to change the cloud environment. 如果要切换回全局 Azure,请再次运行 az cloud set -n AzureCloudIf you want to switch back to Global Azure, run az cloud set -n AzureCloud again.

如果想要在本地使用 Azure CLI,必须已安装 Azure CLI 版本 2.0.68 或更高版本。If you'd like to use the Azure CLI locally, you must have the Azure CLI version 2.0.68 or later installed. 运行 az --version 即可查找版本。Run az --version to find the version. 如果需要安装或升级 CLI,请参阅安装 Azure CLIIf you need to install or upgrade the CLI, see Install Azure CLI.

先决条件Prerequisites

完成前一篇教程Complete the previous tutorials

本教程假定你已完成本系列中前两个教程中的步骤,其中包括:This tutorial assumes you've already completed the steps in the first two tutorials in the series, in which you:

  • 创建 Azure 容器注册表Create Azure container registry
  • 创建示例存储库分支Fork sample repository
  • 克隆示例存储库Clone sample repository
  • 创建 GitHub 个人访问令牌Create GitHub personal access token

在继续之前,请先完成以下教程(如果尚未完成):If you haven't already done so, complete the following tutorials before proceeding:

使用 Azure 容器注册表任务在云中生成容器映像Build container images in the cloud with Azure Container Registry Tasks

使用 Azure 容器注册表任务自动化容器映像生成Automate container image builds with Azure Container Registry Tasks

除了为前面的教程创建的容器注册表以外,还需要创建一个注册表来存储基础映像。In addition to the container registry created for the previous tutorials, you need to create a registry to store the base images. 如果需要,请在与原始注册表不同的位置创建第二个注册表。If you want to, create the second registry in a different location than the original registry.

配置环境Configure the environment

使用适用于环境的值填充这些 shell 环境变量。Populate these shell environment variables with values appropriate for your environment. 此步骤并非必须执行的步骤,但它能让在此教程中执行多个 Azure CLI 命令更容易。This step isn't strictly required, but makes executing the multiline Azure CLI commands in this tutorial a bit easier. 如果未填充这些环境变量,则每当示例命令中出现每个值,都必须手动替换该值。If you don't populate these environment variables, you must manually replace each value wherever it appears in the example commands.

BASE_ACR=<base-registry-name>   # The name of your Azure container registry for base images
ACR_NAME=<registry-name>        # The name of your Azure container registry for application images
GIT_USER=<github-username>      # Your GitHub user account name
GIT_PAT=<personal-access-token> # The PAT you generated in the second tutorial

基础映像更新方案Base image update scenario

本教程将指导完成基础映像更新方案。This tutorial walks you through a base image update scenario. 此方案反映了在其他注册表中创建应用程序映像时,在团队共用的专用容器注册表中管理基础映像的开发工作流。This scenario reflects a development workflow to manage base images in a common, private container registry when creating application images in other registries. 该基础映像可以指定团队共用的操作系统和框架,甚至可以指定共用的服务组件。The base images could specify common operating systems and frameworks used by a team, or even common service components.

例如,在自己注册表中开发应用程序映像的开发人员可以访问共用基础注册表中维护的一组基础映像。For example, developers who develop application images in their own registries can access a set of base images maintained in the common base registry. 基础注册表可以位于另一区域,甚至可以异地复制。The base registry can be in another region or even geo-replicated.

代码示例包括两个 Dockerfile:一个应用程序映像和一个它指定为其基础的映像。The code sample includes two Dockerfiles: an application image, and an image it specifies as its base. 在以下部分,你将创建一个 ACR 任务,用于在将新版基础映像推送到不同 Azure 容器注册表时自动触发应用程序映像的生成。In the following sections, you create an ACR task that automatically triggers a build of the application image when a new version of the base image is pushed to a different Azure container registry.

  • Dockerfile-app:小型 Node.js Web 应用程序,它呈现一个静态 Web 页面,其中显示该应用程序所基于的 Node.js 版本。Dockerfile-app: A small Node.js web application that renders a static web page displaying the Node.js version on which it's based. 该版本字符串是模拟的:显示基础映像中定义的环境变量和 NODE_VERSION 的内容。The version string is simulated: it displays the contents of an environment variable, NODE_VERSION, that's defined in the base image.

  • Dockerfile-baseDockerfile-app 指定为其基础的映像。Dockerfile-base: The image that Dockerfile-app specifies as its base. 它本身基于节点映像,并且包括 NODE_VERSION 环境变量。It is itself based on a Node image, and includes the NODE_VERSION environment variable.

在以下部分,我们将创建一个任务,在基础映像 Dockerfile 中更新 NODE_VERSION 值,并使用 ACR 任务来生成基础映像。In the following sections, you create a task, update the NODE_VERSION value in the base image Dockerfile, then use ACR Tasks to build the base image. ACR 任务将新基础映像推送到注册表时,它会自动触发应用程序映像的生成。When the ACR task pushes the new base image to your registry, it automatically triggers a build of the application image. 可选择本地运行应用程序容器映像,在生成的映像中查看不同版本字符串。Optionally, you run the application container image locally to see the different version strings in the built images.

在本教程中,ACR 任务会生成并推送在 Dockerfile 中指定的应用程序容器映像。In this tutorial, your ACR task builds and pushes an application container image specified in a Dockerfile. ACR 任务也可运行多步骤任务,使用 YAML 文件来定义相关步骤,以便生成并推送多个容器,并可选择对其进行测试。ACR Tasks can also run multi-step tasks, using a YAML file to define steps to build, push, and optionally test multiple containers.

生成基础映像Build the base image

首先使用 az acr build 通过 ACR 任务“快速任务”来生成基础映像。 Start by building the base image with an ACR Tasks quick task, using az acr build. 如本系列教程的第一篇教程中所述,如果生成成功,则此过程不仅会生成映像,还会将其推送到容器注册表。As discussed in the first tutorial in the series, this process not only builds the image, but pushes it to your container registry if the build is successful. 在此示例中,映像将推送到基础映像注册表。In this example, the image is pushed to the base image registry.

az acr build --registry $BASE_ACR --image baseimages/node:9-alpine --file Dockerfile-base .

创建一个任务来跟踪专用基础映像Create a task to track the private base image

接下来,使用 az acr task create 在应用程序映像注册表中创建一个启用托管标识的任务。Next, create a task in the application image registry with az acr task create, enabling a managed identity. 在后续步骤中将使用该托管标识,使任务能够在基础映像注册表中进行身份验证。The managed identity is used in later steps so that the task authenticates with the base image registry.

此示例使用系统分配的标识,但你可以为特定的方案创建并启用用户分配的托管标识。This example uses a system-assigned identity, but you could create and enable a user-assigned managed identity for certain scenarios. 有关详细信息,请参阅使用 Azure 托管标识在 ACR 任务中进行跨注册表的身份验证For details, see Cross-registry authentication in an ACR task using an Azure-managed identity.

az acr task create \
    --registry $ACR_NAME \
    --name taskhelloworld \
    --image helloworld:{{.Run.ID}} \
    --context https://github.com/$GIT_USER/acr-build-helloworld-node.git \
    --file Dockerfile-app \
    --git-access-token $GIT_PAT \
    --arg REGISTRY_NAME=$BASE_ACR.azurecr.cn \
    --assign-identity

重要

在本地 PowerShell 环境中运行上述 CLI cmdlet 时,可能会在控制台上显示以下错误消息:az acr task create: 'utputformat' is not a valid value for '--output'. See 'az acr task create --help'.When you run the above CLI cmdlet on your local PowerShell environment , Maybe there are one following error message showed on your console: az acr task create: 'utputformat' is not a valid value for '--output'. See 'az acr task create --help'.

请替换以下项,然后再次运行 cmdlet。Please replace the following item and run your cmdlet again.

  • --image helloworld:{{.Run.ID}} 替换为 --image 'helloworld:{{.Run.ID}}'Replace --image helloworld:{{.Run.ID}} with --image 'helloworld:{{.Run.ID}}'

此任务类似于上一篇教程中创建的任务。This task is similar to the task created in the previous tutorial. 将提交内容推送到 --context 指定的存储库时,生成任务会指示 ACR 任务触发映像生成。It instructs ACR Tasks to trigger an image build when commits are pushed to the repository specified by --context. 在前一篇教程用于生成映像的 Dockerfile 指定了公共基础映像 (FROM node:9-alpine),而此任务中的 Dockerfile Dockerfile-app 指定的是基础映像注册表中的基础映像:While the Dockerfile used to build the image in the previous tutorial specifies a public base image (FROM node:9-alpine), the Dockerfile in this task, Dockerfile-app, specifies a base image in the base image registry:

FROM ${REGISTRY_NAME}/baseimages/node:9-alpine

使用此配置可以轻松模拟稍后在本教程中对基础映像进行的框架修补。This configuration makes it easy to simulate a framework patch in the base image later in this tutorial.

为标识授予对基础注册表的提取权限Give identity pull permissions to base registry

若要为任务的托管标识授予从基础映像注册表提取映像的权限,请先运行 az acr task show 获取标识的服务主体 ID。To give the task's managed identity permissions to pull images from the base image registry, first run az acr task show to get the service principal ID of the identity. 然后运行 az acr show 获取基础注册表的资源 ID:Then run az acr show to get the resource ID of the base registry:

# Get service principal ID of the task
principalID=$(az acr task show --name taskhelloworld --registry $ACR_NAME --query identity.principalId --output tsv) 

# Get resource ID of the base registry
baseregID=$(az acr show --name $BASE_ACR --query id --output tsv) 

运行 az role assignment create,为托管标识分配对注册表的提取权限:Assign the managed identity pull permissions to the registry by running az role assignment create:

az role assignment create \
  --assignee $principalID \
  --scope $baseregID --role acrpull 

将目标注册表凭据添加到任务Add target registry credentials to the task

运行 az acr task credential add 将凭据添加到任务。Run az acr task credential add to add credentials to the task. 传递 --use-identity [system] 参数,指示任务的系统分配的托管标识可以访问凭据。Pass the --use-identity [system] parameter to indicate that the task's system-assigned managed identity can access the credentials.

az acr task credential add \
  --name taskhelloworld \
  --registry $ACR_NAME \
  --login-server $BASE_ACR.azurecr.cn \
  --use-identity [system] 

手动运行任务Manually run the task

使用 az acr task run 手动触发任务并生成应用程序映像。Use az acr task run to manually trigger the task and build the application image. 此步骤是必需的,这样该任务才能跟踪应用程序映像对基础映像的依赖性。This step is needed so that the task tracks the application image's dependency on the base image.

az acr task run --registry $ACR_NAME --name taskhelloworld

任务完成后,如果还要完成以下可选步骤,请记下“运行 ID”(例如“da6”) 。Once the task has completed, take note of the Run ID (for example, "da6") if you wish to complete the following optional step.

可选:本地运行应用程序容器Optional: Run application container locally

如果在本地运行(而不是在本地 Shell 中运行)并且已安装 Docker,请运行容器,以查看 Web 浏览器中呈现的应用程序,然后再重新生成其基础映像。If you're working locally (not in the local Shell), and you have Docker installed, run the container to see the application rendered in a web browser before you rebuild its base image. 如果使用的是本地 Shell,请跳过此部分(Cloud Shell 不支持 az acr logindocker run)。If you're using the local Shell, skip this section (Cloud Shell does not support az acr login or docker run).

首先,使用 az acr login 在容器注册表中进行身份验证:First, authenticate to your container registry with az acr login:

az acr login --name $ACR_NAME

然后,使用 docker run 在本地运行容器。Now, run the container locally with docker run. 将 <run-id> 替换为上一步骤的输出中的“运行 ID”(例如“da6”)。Replace <run-id> with the Run ID found in the output from the previous step (for example, "da6"). 此示例将容器命名为 myapp,并包含 --rm 参数,以便在停止容器后将其删除。This example names the container myapp and includes the --rm parameter to remove the container when you stop it.

docker run -d -p 8080:80 --name myapp --rm $ACR_NAME.azurecr.cn/helloworld:<run-id>

在浏览器中导航到 http://localhost:8080,应看见呈现在 Web 页面中的 Node.js 版本号,如下所示。Navigate to http://localhost:8080 in your browser, and you should see the Node.js version number rendered in the web page, similar to the following. 在稍后的步骤中,会通过向版本字符串中添加“a”来提升版本。In a later step, you bump the version by adding an "a" to the version string.

显示浏览器中呈现的示例应用程序的屏幕截图。

若要停止并删除容器,请运行以下命令:To stop and remove the container, run the following command:

docker stop myapp

列出生成List the builds

接下来,使用 az acr task list-runs 命令列出 ACR 任务对注册表完成的任务运行:Next, list the task runs that ACR Tasks has completed for your registry using the az acr task list-runs command:

az acr task list-runs --registry $ACR_NAME --output table

如果已完成之前的教程(并且没有删除注册表),应看到如下所示的输出。If you completed the previous tutorial (and didn't delete the registry), you should see output similar to the following. 记下任务运行的数目以及最新的运行 ID,以便在后续部分中更新基础映像后对比输出。Take note of the number of task runs, and the latest RUN ID, so you can compare the output after you update the base image in the next section.

$ az acr task list-runs --registry $ACR_NAME --output table

RUN ID    TASK            PLATFORM    STATUS     TRIGGER     STARTED               DURATION
--------  --------------  ----------  ---------  ----------  --------------------  ----------
da6       taskhelloworld  Linux       Succeeded  Manual      2018-09-17T23:07:22Z  00:00:38
da5                       Linux       Succeeded  Manual      2018-09-17T23:06:33Z  00:00:31
da4       taskhelloworld  Linux       Succeeded  Git Commit  2018-09-17T23:03:45Z  00:00:44
da3       taskhelloworld  Linux       Succeeded  Manual      2018-09-17T22:55:35Z  00:00:35
da2       taskhelloworld  Linux       Succeeded  Manual      2018-09-17T22:50:59Z  00:00:32
da1                       Linux       Succeeded  Manual      2018-09-17T22:29:59Z  00:00:57

更新基础映像Update the base image

在这里模拟基础映像中的框架补丁。Here you simulate a framework patch in the base image. 编辑“Dockerfile-base”,并在 NODE_VERSION 中定义的版本号后面添加一个“a” :Edit Dockerfile-base, and add an "a" after the version number defined in NODE_VERSION:

ENV NODE_VERSION 9.11.2a

运行快速任务来生成修改后的基础映像。Run a quick task to build the modified base image. 记下输出中的“运行 ID” 。Take note of the Run ID in the output.

az acr build --registry $BASE_ACR --image baseimages/node:9-alpine --file Dockerfile-base .

生成完成并且 ACR 任务将新基础映像推送到注册表后,它会触发应用程序映像的生成。Once the build is complete and the ACR task has pushed the new base image to your registry, it triggers a build of the application image. 之前创建的任务触发应用程序映像生成可能需要一些时间,因为它必须检测新生成和推送的基础映像。It may take few moments for the task you created earlier to trigger the application image build, as it must detect the newly built and pushed base image.

列出已更新的生成List updated build

更新基础映像后,请再次列出任务运行,以便与之前的列表进行比较。Now that you've updated the base image, list your task runs again to compare to the earlier list. 如果开始时输出没有区别,可定期运行该命令以查看出现在列表中的新任务运行。If at first the output doesn't differ, periodically run the command to see the new task run appear in the list.

az acr task list-runs --registry $ACR_NAME --output table

输出如下所示。Output is similar to the following. 最后执行的生成的触发器应为“映像更新”,指示任务是通过基础映像的快速任务启动的。The TRIGGER for the last-executed build should be "Image Update", indicating that the task was kicked off by your quick task of the base image.

$ az acr task list-runs --registry $ACR_NAME --output table

Run ID    TASK            PLATFORM    STATUS     TRIGGER       STARTED               DURATION
--------  --------------  ----------  ---------  ------------  --------------------  ----------
da8       taskhelloworld  Linux       Succeeded  Image Update  2018-09-17T23:11:50Z  00:00:33
da7                       Linux       Succeeded  Manual        2018-09-17T23:11:27Z  00:00:35
da6       taskhelloworld  Linux       Succeeded  Manual        2018-09-17T23:07:22Z  00:00:38
da5                       Linux       Succeeded  Manual        2018-09-17T23:06:33Z  00:00:31
da4       taskhelloworld  Linux       Succeeded  Git Commit    2018-09-17T23:03:45Z  00:00:44
da3       taskhelloworld  Linux       Succeeded  Manual        2018-09-17T22:55:35Z  00:00:35
da2       taskhelloworld  Linux       Succeeded  Manual        2018-09-17T22:50:59Z  00:00:32
da1                       Linux       Succeeded  Manual        2018-09-17T22:29:59Z  00:00:57

如果想要执行以下可选步骤运行新生成的容器,以查看更新的版本号,请记下映像更新触发的生成的“运行 ID”值(在之前的输出中为“da8”) 。If you'd like to perform the following optional step of running the newly built container to see the updated version number, take note of the RUN ID value for the Image Update-triggered build (in the preceding output, it's "da8").

可选:运行新生成的映像Optional: Run newly built image

如果正在本地运行并且已安装 Docker,请在新应用程序映像的生成完成后运行它。If you're working locally, and you have Docker installed, run the new application image once its build has completed. <run-id> 替换为上一步骤中获取的“运行 ID”。Replace <run-id> with the RUN ID you obtained in the previous step.

docker run -d -p 8081:80 --name updatedapp --rm $ACR_NAME.azurecr.cn/helloworld:<run-id>

在浏览器中导航到 http://localhost:8081 ,应看见网页上显示有更新后的 Node.js 版本编号(带有“a”):Navigate to http://localhost:8081 in your browser, and you should see the updated Node.js version number (with the "a") in the web page:

浏览器中呈现示例应用程序的屏幕截图

请务必注意,使用新版本号更新“基础”映像,但是最后生成的“应用程序”映像显示新版本 。What's important to note is that you updated your base image with a new version number, but the last-built application image displays the new version. ACR 任务选取了对基础映像的更改,并自动重新生成了应用程序映像。ACR Tasks picked up your change to the base image, and rebuilt your application image automatically.

若要停止并删除容器,请运行以下命令:To stop and remove the container, run the following command:

docker stop updatedapp

后续步骤Next steps

在本教程中,我们已了解在更新映像的基础映像后,如何使用任务来自动触发容器映像生成。In this tutorial, you learned how to use a task to automatically trigger container image builds when the image's base image has been updated. 现在,请转到下一个教程学习如何按照定义的计划触发任务。Now, move on to the next tutorial to learn how to trigger tasks on a defined schedule.