Build and publish Docker images to Azure Container Registry

Azure DevOps Services | Azure DevOps Server 2022

Using Azure Pipelines, you can set up a pipeline workflow to build and publish your Docker images to Azure Container Registry. In this article, you will learn how to:

  • Create an Azure Container Registry
  • Set up a self-hosted agent on an Azure VM
  • Set up the managed service identity
  • Create a Docker Registry service connection
  • Build and publish your image to Azure Container Registry

Prerequisites

Get the code

Fork or clone the sample app to follow along with this tutorial.

https://github.com/MicrosoftDocs/pipelines-javascript-docker

Create an Azure Container Registry

  1. Navigate to Azure portal.

  2. Select Create a resource from the left navigation panel, and then select Containers then Container Registry.

  3. Select your Subscription and then select your Resource group or create a new one.

  4. Enter a Registry name for your container registry. The registry name must be unique within Azure and must contain at least 5 characters.

  5. Select your preferred Location and SKU and then select Review + create.

  6. Review your settings and then select Create when you're done.

Set up a self-hosted agent VM

To use Managed Service Identity with Azure Pipelines to publish Docker images to Azure Container Registry, we must set up our own self-hosted agent on an Azure VM.

Create a VM

  1. Navigate to Azure portal.

  2. Select Create a resource from the left navigation panel, and then select Virtual machine -> Create.

  3. Select your Subscription and then select the Resource group you used to create your container registry.

  4. Give your virtual machine a name and choose an Image.

  5. Enter your Username and Password, and then select Review + create.

  6. Review your settings, and then select Create when you're done.

  7. Select Go to resource when the deployment is complete.

Create an agent pool

  1. From your Azure DevOps project, select the gear icon gear icon to navigate to your Project settings.

  2. Select Agent pools, and then select Add pool.

  3. Select New, and then select Self-hosted from the Pool type dropdown menu.

  4. Give your pool a name, and then check Grant access permission to all pipelines checkbox.

  5. Select Create when you're done.

  6. Now select the pool you just created, and then select New agent.

  7. We will be using the instructions in this window to set up your agent in the VM you created earlier. Select the Copy button to copy the download link to your clipboard.

    A screenshot showing how to set up an agent.

Create a personal access token

  1. From your Azure DevOps project, select User Settings, and then select Personal Access Tokens.

  2. Select New Token to create a new Personal Access Token.

  3. Enter a name for your PAT, and then choose an expiration date.

  4. Select Custom defined in Scopes, and then select Show all scopes.

  5. Select Agent Pools -> Read & manage, and Deployment Groups -> Read & manage.

  6. Select Create when you're done, and save your PAT in a safe location.

Set up a self-hosted agent

  1. In Azure portal, connect to your VM.

  2. In an elevated PowerShell command prompt, run the following command to download the agent.

    Invoke-WebRequest -URI <YOUR_AGENT_DOWNLOAD_LINK> -UseBasicParsing  -OutFile <FILE_PATH> 
    ##Example: Invoke-WebRequest -URI https://vstsagentpackage.azureedge.net/agent/2.213.2/vsts-agent-win-x64-2.213.2.zip -OutFile C:\vsts-agent-win-x64-2.213.2.zip
    
  3. Run the following command to extract and create your agent.

    mkdir agent ; cd agent
    Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("<FILE_PATH>", "$PWD")
    
  4. Run the following command to start configuring your agent.

    .\config.cmd
    
  5. Enter your server URL when asked for input. Example: https://dev.azure.com/fabrikamFiber

  6. Press Enter when prompted for the authentication type to choose PAT authentication.

  7. Paste your personal access token that you created earlier and then press enter.

  8. Enter the name of your agent pool, and then enter your agent name.

  9. Leave the default value for work folder, and then enter Y if you want to run your agent as a service.

    A screenshot showing how to set up an agent on an Azure VM.

  10. Now that the agent is ready to start listening for jobs, let's install Docker on our VM. Run the following command to download Docker.

    Invoke-WebRequest -URI https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe -OutFile <DOWNLOAD_PATH>
    
  11. Navigate to your download path, and then run the following command to install and start Docker.

    Start-Process 'Docker%20Desktop%20Installer.exe' -Wait install
    
  12. Now navigate back to your agent folder, and run the cmd file to run the agent on your Azure VM.

    .\run.cmd
    
  13. Your agent should be listed now in your Agent pool -> Agents in the Azure DevOps portal.

    A screenshot showing the agent available in the agents tab.

Set up the managed identity

  1. In Azure portal, navigate to the VM you created earlier.

  2. Select Identity from the left navigation panel, and then enable the System assigned identity.

  3. Select Save when you're done and then confirm your choice.

    A screenshot showing how to enable system-assigned identity.

  4. Select Azure role assignments, and then select Add role assignment.

  5. Select Resource group from the Scope dropdown menu.

  6. Select your Subscription and your Resource group, and then select the AcrPush role.

  7. Repeat the steps 5 & 6 to add the AcrPull role.

    A screenshot showing how to set up acrpull and push roles.

Create a Docker registry service connection

  1. From your Azure DevOps project, select the gear icon gear icon to navigate to your Project settings.

  2. Select Service connections from the left pane.

  3. Select New service connection, and then select Docker Registry then Next.

  4. Select Azure Container Registry, and then select Managed Service Identity as your Authentication Type.

  5. Enter your Subscription ID Subscription name, and your Azure container registry login server. Paste your VM's system assigned Tenant ID that you created in the previous step in the Tenant ID text field.

  6. Enter a name for your service connection, and then check the Grant access permission to all pipelines checkbox. To select this option, you'll need the service connection Administrator role.

  7. Select Save when you are done.

    A screenshot showing how to set up a docker registry service connection MSI.

Build and publish to Azure Container Registry

  1. From your Azure DevOps project, select Pipelines and then select Create Pipeline.

  2. Select the service hosting your source code (Azure Repos, GitHub etc.).

  3. Select your repository, and then select Starter pipeline.

  4. Delete the default yaml pipeline and use the following snippet:

    trigger:
    - main
    
    variables:
      dockerRegistryServiceConnection: '<SERVICE_CONNECTION_NAME>'
      imageRepository: '<IMAGE_NAME>'
      dockerfilePath: '$(Build.SourcesDirectory)/app/Dockerfile'
      tag: '$(Build.BuildId)'
    
    stages:
    - stage: Build
      displayName: Build and publish stage
      jobs:
      - job: Build
        displayName: Build job
        pool:
          name: '<YOUR_AGENT_POOL_NAME>'
        steps:
        - task: DockerInstaller@0
          inputs:
            dockerVersion: '17.09.0-ce'
    
        - task: Docker@2
          displayName: Build and publish image to Azure Container Registry
          inputs:
            command: buildAndPush
            containerRegistry: $(dockerRegistryServiceConnection)
            repository: $(imageRepository)
            dockerfile: $(dockerfilePath)
            tags: |
              $(tag)
    
  5. Once the pipeline run is complete, you can verify your image in Azure. Navigate to your Azure Container Registry in Azure portal, and then select Repositories.

    A screenshot showing the image in Azure portal.

Clean up resources

If you don't plan to continue using this application, delete the resource group to avoid incurring ongoing charges.

az group delete --name myapp-rg