Tutorial: Automate container image builds when a base image is updated in an Azure container registry
ACR Tasks supports automated container 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.
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 the same registry. You can also try a tutorial to create an ACR task that triggers an image build when a base image is pushed to another Azure container registry.
In this tutorial:
- Build the base image
- Create an application image in the same registry to track the base image
- Update the base image to trigger an application image task
- Display the triggered task
- Verify updated application image
Prerequisites
Complete the previous tutorials
This tutorial assumes you've already configured your environment and completed the steps in the first two tutorials in the series, in which you:
- Create Azure container registry
- Fork sample repository
- Clone sample repository
- Create GitHub personal access token
If you haven't already done so, complete the following tutorials before proceeding:
Build container images in the cloud with Azure Container Registry Tasks
Automate container image builds with Azure Container Registry Tasks
Configure the environment
Use the Bash environment in Azure Cloud Shell. For more information, see Quickstart for Bash in Azure Cloud Shell.
If you prefer to run CLI reference commands locally, install the Azure CLI. If you're running on Windows or macOS, consider running Azure CLI in a Docker container. For more information, see How to run the Azure CLI in a Docker container.
If you're using a local installation, sign in to the Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. For other sign-in options, see Sign in with the Azure CLI.
When you're prompted, install the Azure CLI extension on first use. For more information about extensions, see Use extensions with the Azure CLI.
Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.
- This article requires version 2.0.46 or later of the Azure CLI. If using Azure Cloud Shell, the latest version is already installed.
Populate these shell environment variables with values appropriate for your environment. 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.
ACR_NAME=<registry-name> # The name of your Azure container registry
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 in which a base image and an application image are maintained in a single registry.
The code sample includes two Dockerfiles: an application image, and an image it specifies as its base. 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 the same container registry.
Dockerfile-app: A small Node.js web application that renders a static web page displaying the Node.js version on which it's based. The version string is simulated: it displays the contents of an environment variable,
NODE_VERSION
, that's defined in the base image.Dockerfile-base: The image that
Dockerfile-app
specifies as its base. It is itself based on a Node image, and includes theNODE_VERSION
environment variable.
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. 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.
In this tutorial, your ACR task builds and pushes an application container image specified in a Dockerfile. 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
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.
az acr build --registry $ACR_NAME --image baseimages/node:15-alpine --file Dockerfile-base .
Create a task
Next, create a task with az acr task create:
az acr task create \
--registry $ACR_NAME \
--name baseexample1 \
--image helloworld:{{.Run.ID}} \
--arg REGISTRY_NAME=$ACR_NAME.azurecr.io \
--context https://github.com/$GIT_USER/acr-build-helloworld-node.git#master \
--file Dockerfile-app \
--git-access-token $GIT_PAT
This task is similar to the task created in the previous tutorial. It instructs ACR Tasks to trigger an image build when commits are pushed to the repository specified by --context
. While the Dockerfile used to build the image in the previous tutorial specifies a public base image (FROM node:15-alpine
), the Dockerfile in this task, Dockerfile-app, specifies a base image in the same registry:
FROM ${REGISTRY_NAME}/baseimages/node:15-alpine
This configuration makes it easy to simulate a framework patch in the base image later in this tutorial.
Build the application container
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 baseexample1
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
If you're working locally (not in the Cloud Shell), and you have Docker installed, run the container to see the application rendered in a web browser before you rebuild its base image. If you're using the Cloud Shell, skip this section (Cloud Shell does not support az acr login
or docker run
).
First, authenticate to your container registry with az acr login:
az acr login --name $ACR_NAME
Now, run the container locally with docker run
. Replace <run-id> with the Run ID found in the output from the previous step (for example, "da6"). 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.io/helloworld:<run-id>
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. 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
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. 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.
RUN ID TASK PLATFORM STATUS TRIGGER STARTED DURATION
-------- -------------- ---------- --------- --------- -------------------- ----------
cax baseexample1 linux Succeeded Manual 2020-11-20T23:33:12Z 00:00:30
caw taskhelloworld linux Succeeded Commit 2020-11-20T23:16:07Z 00:00:29
cav example2 linux Succeeded Commit 2020-11-20T23:16:07Z 00:00:55
cau example1 linux Succeeded Commit 2020-11-20T23:16:07Z 00:00:40
cat taskhelloworld linux Succeeded Manual 2020-11-20T23:07:29Z 00:00:27
Update the base image
Here you simulate a framework patch in the base image. Edit Dockerfile-base, and add an "a" after the version number defined in NODE_VERSION
:
ENV NODE_VERSION 15.2.1a
Run a quick task to build the modified base image. Take note of the Run ID in the output.
az acr build --registry $ACR_NAME --image baseimages/node:15-alpine --file Dockerfile-base .
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.
Run ID TASK PLATFORM STATUS TRIGGER STARTED DURATION
-------- -------------- ---------- --------- ------------ -------------------- ----------
ca11 baseexample1 linux Succeeded Image Update 2020-11-20T23:38:24Z 00:00:34
ca10 taskhelloworld linux Succeeded Image Update 2020-11-20T23:38:24Z 00:00:24
cay linux Succeeded Manual 2020-11-20T23:38:08Z 00:00:22
cax baseexample1 linux Succeeded Manual 2020-11-20T23:33:12Z 00:00:30
caw taskhelloworld linux Succeeded Commit 2020-11-20T23:16:07Z 00:00:29
cav example2 linux Succeeded Commit 2020-11-20T23:16:07Z 00:00:55
cau example1 linux Succeeded Commit 2020-11-20T23:16:07Z 00:00:40
cat taskhelloworld linux Succeeded Manual 2020-11-20T23:07:29Z 00:00:27
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 "ca11").
Optional: Run newly built image
If you're working locally (not in the Cloud Shell), and you have Docker installed, run the new application image once its build has completed. Replace <run-id>
with the RUN ID you obtained in the previous step. If you're using the Cloud Shell, skip this section (Cloud Shell does not support docker run
).
docker run -d -p 8081:80 --name updatedapp --rm $ACR_NAME.azurecr.io/helloworld:<run-id>
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 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.
For a complete workflow to manage base images originating from a public source, see How to consume and maintain public content with Azure Container Registry Tasks.
Now, move on to the next tutorial to learn how to trigger tasks on a defined schedule.