This article is based on Part 3 of Chris Sainty’s series Containerising Blazor Applications With Docker, originally published at chrissainty.com. While the example project is a Blazor Server application, the pipeline technique described here applies to any Docker image.
Series overview:
- Part 1 – Containerising a Blazor Server App
- Part 2 – Containerising a Blazor WebAssembly App
- Part 3 – Publishing to Azure Container Registry using Azure Pipelines (this post)
Overview
Parts 1 and 2 covered how to containerise Blazor applications so they run locally inside Docker containers. The natural next step is automation: how do you build Docker images as part of a CI pipeline, and where do you store those images once they’re built?
This post answers both questions. You’ll learn how to:
- Create an Azure Container Registry (ACR) to store Docker images.
- Set up an Azure Pipelines CI build that automatically builds your Docker image on every push.
- Configure the pipeline to push the built image to ACR using a service connection.
The example project is hosted on GitHub, but Azure Pipelines supports many other source control providers, so the approach translates with minimal adjustment.
Creating an Azure Container Registry
Azure Container Registry (ACR) is Azure’s managed Docker image hosting service, conceptually similar to Docker Hub. It provides a private registry where you can store, version, and pull container images.
Step 1: Open Container Registries in the Azure Portal
Log in to the Azure Portal, select All Services from the left-hand menu, and search for Container registries.

Step 2: Add a New Registry
When the blade loads, click Add at the top of the screen.

Step 3: Configure the Registry
Fill in the Create container registry form:
- Registry name – must be globally unique within Azure.
- Subscription, Resource group, and Location – choose values appropriate for your environment.
- Admin user – leave this disabled. You will connect Azure Pipelines to the registry using a service connection, which is the recommended approach.
- SKU – select the pricing tier that fits your needs. Basic is sufficient for development and testing scenarios.

Click Create. The registry will be provisioned within a minute or two. Once it’s ready, move on to setting up Azure Pipelines.
Setting Up Azure Pipelines
Azure Pipelines is a CI/CD service that is part of Azure DevOps. It can build, test, and deploy code targeting any platform or cloud. A free tier is available for public and private projects.
Step 1: Create an Azure DevOps Project
Sign in at dev.azure.com. If you don’t already have an organisation, you’ll be prompted to create one. Then click New Project in the top-right corner, give the project a name, and set its visibility (public or private).

Click Create and you’ll land on the project home screen.

Step 2: Create a New Pipeline
In the left-hand menu, navigate to Pipelines → Builds, then click New pipeline.

Step 3: Connect to Source Control
The new pipeline wizard walks you through four steps. The first is connecting to your source code repository. Select GitHub (or whichever provider hosts your code — Azure Repos, Bitbucket, and others are also supported).

Authorise access if prompted, then select the repository you want to build from the list.

Step 4: Configure the Pipeline Template
In the configuration step, you’ll see a list of pipeline templates. Click Show More if needed, scroll down, and select Docker.

A drawer appears asking you to locate your Dockerfile. The path field is case-sensitive. If your Dockerfile uses a lowercase d (i.e., dockerfile rather than Dockerfile), update the field accordingly — for example, **/dockerfile. Click Validate and configure.

Step 5: Review and Save the Pipeline YAML
The wizard generates a azure-pipelines.yml file. Review it, then click Save and run.

You’ll be asked whether to commit directly to main/master or to a new branch. Committing to a feature branch (e.g., azure-pipelines) is recommended — it lets you iterate on the pipeline configuration and merge it via a pull request once everything works correctly.

After the commit, Azure Pipelines triggers a build automatically. When it completes successfully, you’ll see the build summary screen.

At this point the Docker image is being built by Azure Pipelines on every push. The next step is to push that image to your Azure Container Registry automatically.
Publishing the Image to Azure Container Registry
Step 1: Create a Service Connection
Azure Pipelines needs permission to push images to your ACR. You grant this through a service connection.
Go to Project settings (bottom-left of the screen) and select Service connections under the Pipelines section. Click New service connection and choose Docker Registry from the list.

In the modal that appears, select Azure Container Registry, then:
- Give the connection a meaningful name (e.g.,
AzureContainerRegistry). You’ll reference this name in your pipeline YAML. - Select your Azure subscription.
- Select the container registry you created earlier.

Click OK to save the connection.
Step 2: Update the Pipeline YAML
Go to Pipelines → Builds, find your pipeline, and click Edit.

Replace the existing Docker task with the following, updating repository and containerRegistry to match your setup:
- task: Docker@2
displayName: Build and push image to container registry
inputs:
command: buildAndPush
repository: demos/BlazorServerWithDocker
dockerfile: '**/dockerfile'
containerRegistry: AzureContainerRegistry
tags: |
$(Build.BuildId)Code language: CSS (css)
Key changes explained:
command: buildAndPush— Builds the image and immediately pushes it to the registry in a single task, replacing the earlierbuild-only command.repository— The path within the registry where the image will be stored. If the repository doesn’t exist in ACR, it will be created automatically on first push.containerRegistry— The name of the service connection you created in Step 1. This is how the pipeline authenticates to ACR.tags— One or more tags to apply to the image. Using the built-in$(Build.BuildId)variable gives each build a unique, traceable tag.
Note on the $(tag) variable: The original source uses $(tag) as the image tag. This is a pipeline variable that must be defined in the pipeline’s variable settings or passed at runtime. Using $(Build.BuildId) is a common alternative that works without additional setup. Verify which approach suits your workflow.
Step 3: Save and Run the Updated Pipeline
Click Save. You can add a commit message in the dialogue that appears before the updated YAML is committed to your branch.

Saving triggers a new build automatically. If it doesn’t, click Run at the top-right of the pipeline editor.

After the build completes successfully, you’ll see a green build summary.

Step 4: Verify the Image in ACR
Head back to the Azure Portal and open your Container Registry. Select Repositories from the left menu. You should see the repository you specified in the pipeline YAML. Click on it to view the image and its tags.

Summary
This walkthrough covered the end-to-end process of automating Docker image builds and publishing with Azure Pipelines and Azure Container Registry:
- Created an ACR instance in the Azure Portal with the Admin user disabled.
- Set up an Azure Pipelines build connected to a GitHub repository.
- Used the Docker pipeline template to generate a working
azure-pipelines.yml. - Added a Docker Registry service connection to authenticate the pipeline to ACR.
- Updated the pipeline task to use
buildAndPush, pushing the image to ACR on every build.
Although the example uses a Blazor Server application, the pipeline configuration is not Blazor-specific. Any project with a valid Dockerfile can be built and published to ACR using the same steps.
Original article by Chris Sainty — chrissainty.com