Deploy to Azure Container App from Azure Container Registry using a CI/CD Azure DevOps Pipeline and Azure CLI

Azure Container Apps are relatively new in Azure, still in Preview as of writing this blog post. In this blog, I will be deploying to Azure Container App from Azure Container Registry using a CI/CD Azure DevOps Pipeline and Azure CLI.

You may be thinking, what is the difference between a Container App and Container Instance?

  • Container instance is a single isolated pod/container on demand
  • Microsoft reference a container instance as a lower-level “building block” option compared to Container Apps
  • Scaling and load balancing is not provided with Container Instances
  • Container Apps provide the ability to scale & use of certificates on top of your container(s)

The Deployment Overview

Once we commit a change to the source code – we want the Container Application to have been deployed with the latest commit automatically.

Lets look at this further with the below diagram:

  1. Developers commits code change to Azure Repo
  2. Azure Pipeline trigger, triggers a build with merge to main branch happens
  3. Azure Pipeline flows throw the stages
  4. Azure Pipeline Builds and pushes latest change in code to a new image within the Azure Container Registry
  5. Stage deploy_container_appwill pull the latest image from Azure Container Registry and deploy this to Azure Container Instance
  6. Log Analytics can be reviewed regarding logs from the container environment
  7. Back to the developer to commit next change and this process happens again

Azure DevOps Pipeline Overview

The pipeline will consist of 4 stages:

  • create_acr will create resource group , container registry to where the sample application will be uploaded to and also log analytics workspace that the container environment will connect to
  • build will build the sample application and push to the Container Registry created in create_acr stage
  • create_container_environment Will create the container environment to host the container app that will be deployed in the final stage
  • deploy_container_app will deploy the container app from image created in build stage

Please note:- As the date of this blog post; there is no set tasks in Azure DevOps for deploying container apps – I will be using provided Az CLI

Azure DevOps Pipeline Setup

For this setup, I will go through each of the 4 stages of the pipeline

Prior to setup, a variable group is required, this will store the Azure Container Registry Login Password. Check out this blog regarding Referencing Variable Groups in Azure DevOps Pipeline Templates

Variable group azure-container-app has been created

create_acr stage

The first stage & base of the pipeline; this stage will be the initial base of the Azure DevOps Pipeline along with creating:

  • Azure Resource Group azure-container-rg that will be used to deploy all additional resources into
  • Azure Container Registry tamopsacrcontainers that will be used to store the sample application deployed in stage build
  • Azure Log Analytics tamopsacrcontainersla to send container environment data

Notce the trigger reference(highlighted)? This will run the pipeline each time there is a merge to the main branch

name: $(BuildDefinitionName)_$(date:yyyyMMdd)$(rev:.r)

trigger:
  batch: true
  branches:
    include:
    - main

variables:
  - group: azure-container-app

stages :
  - stage: create_acr
    jobs:
      - job: "create_acr"
        steps:
          - task: AzureCLI@2
            displayName: 'Deploy RG and ACR'
            inputs:
              azureSubscription: 'thomasthorntoncloud'
              scriptType: bash
              scriptLocation: inlineScript
              addSpnToEnvironment: true
              inlineScript: |
                #!/bin/bash

                RESOURCE_GROUP="azure-container-rg"
                LOCATION="westeurope"
                LOG_ANALYTICS_WORKSPACE="tamopsacrcontainersla"
                ACR="tamopsacrcontainers"

                az group create -l $LOCATION -n $RESOURCE_GROUP
                az acr create -g $RESOURCE_GROUP -n $ACR --sku basic --admin-enabled true
                az monitor log-analytics workspace create -g $RESOURCE_GROUP --workspace-name $LOG_ANALYTICS_WORKSPACE

Run this initial stage, you will have deployed successfully the three resources

As the Azure Container Registry has been deployed with admin enabled, grab the password from the registry in Access Keys settings and store it within variable group as secret name acrpassword

Docker Registry Service Connection creation

With the ACR deployed, prior to adding the stage build we will now create a Docker Registry service connection within Azure DevOps

Inside Azure DevOps -> Project settings -> Service Connections -> Docker Service Connection

Select relevant subscription & newly created Azure container registry

I will create the service connection with name: tamopsacrcontainers – this will be referenced within the pipeline that will be created

build stage

Moving onto the build stage – this is where the sample app will be built and image pushed to container registry:

  • Using the tag reference $(Build.BuildId) will tag the image with the latest BuildId – each time the pipeline runs, a new image is created – the beginning of CI/CD 🙂
  • containerRegistry is referencing the service connection created above
  - stage: Build
    dependsOn: [create_acr]
    displayName: Build sample app
    jobs:  
    - job: Build
      displayName: Build job
      steps:
      - task: Docker@2
        displayName: Build and push sample app to container registry
        inputs:
          command: buildAndPush
          repository: 'sampleapp'
          dockerfile: '$(Build.SourcesDirectory)/aspnet-core-dotnet-core/Dockerfile'
          containerRegistry: 'tamopsacrcontainers'
          tags: '$(Build.BuildId)'

A successful run of this stage will upload the latest Image to Azure Container Registry as below

create_container_environment stage

Prior to deploying a Container App – a container environment is required

Azure Container Apps environments.
image reference: docs.microsoft.com
  - stage: create_container_environment
    dependsOn: [Build]
    jobs:
      - job: "deploy_app"
        steps:
          - task: AzureCLI@2
            displayName: 'Create container app environment'
            inputs:
              azureSubscription: 'thomasthorntoncloud'
              scriptType: bash
              scriptLocation: inlineScript
              addSpnToEnvironment: true
              inlineScript: |
                #!/bin/bash
                az config set extension.use_dynamic_install=yes_without_prompt
                az provider register --namespace Microsoft.App

                RESOURCE_GROUP="azure-container-rg"
                LOCATION="westeurope"
                LOG_ANALYTICS_WORKSPACE="tamopsacrcontainersla"
                CONTAINERAPPS_ENVIRONMENT="tamops-environment"

                LOG_ANALYTICS_WORKSPACE_CLIENT_ID=`az monitor log-analytics workspace show --query customerId -g $RESOURCE_GROUP -n $LOG_ANALYTICS_WORKSPACE -o tsv | tr -d '[:space:]'`
                LOG_ANALYTICS_WORKSPACE_CLIENT_SECRET=`az monitor log-analytics workspace get-shared-keys --query primarySharedKey -g $RESOURCE_GROUP -n $LOG_ANALYTICS_WORKSPACE -o tsv | tr -d '[:space:]'`

                az containerapp env create \
                -n $CONTAINERAPPS_ENVIRONMENT \
                -g $RESOURCE_GROUP \
                --logs-workspace-id $LOG_ANALYTICS_WORKSPACE_CLIENT_ID \
                --logs-workspace-key $LOG_ANALYTICS_WORKSPACE_CLIENT_SECRET \
                -l $LOCATION

Single environment or multiple? Have a look at some reasons to deploy container environments and reasons possibly for different environments (taken from docs.microsoft.com)

Reasons to deploy container apps to the same environment include situations when you need to:

  • Manage related services
  • Deploy different applications to the same virtual network
  • Have applications communicate with each other using Dapr
  • Have applications to share the same Dapr configuration
  • Have applications share the same log analytics workspace

Reasons to deploy container apps to different environments include situations when you want to ensure:

  • Two applications never share the same compute resources
  • Two applications can’t communicate with each other via Dapr

deploy_container_app stage

The final stage 🙂 – where the container app will be deployed

  - stage: deploy_container_app
    dependsOn: [create_container_environment]
    jobs:
      - job: "deploy_app"
        steps:
          - task: AzureCLI@2
            displayName: 'Deploy app to Container App'
            inputs:
              azureSubscription: 'thomasthorntoncloud'
              scriptType: bash
              scriptLocation: inlineScript
              addSpnToEnvironment: true
              inlineScript: |
                #!/bin/bash
                az config set extension.use_dynamic_install=yes_without_prompt
                az provider register --namespace Microsoft.App

                RESOURCE_GROUP="azure-container-rg"
                LOG_ANALYTICS_WORKSPACE="tamopsacrcontainersla"
                CONTAINERAPPS_ENVIRONMENT="tamops-environment"

                az containerapp create \
                  --name tamopsapp \
                  --resource-group $RESOURCE_GROUP \
                  --environment $CONTAINERAPPS_ENVIRONMENT \
                  --image tamopsacrcontainers.azurecr.io/sampleapp:'$(Build.BuildId)' \
                  --min-replicas 2 \
                  --max-replicas 2 \
                  --registry-server tamopsacrcontainers.azurecr.io \
                  --registry-username tamopsacrcontainers \
                  --registry-password $(acrpassword) \
                  --target-port 80 \
                  --ingress 'external'

Please note, the above pipeline requires a change once ran initially – it has been highlighted, after first initial deployment az containerapp create needs swapped to az containerapp update with the following syntax

                az containerapp update \
                  --name tamopsapp \
                  --resource-group $RESOURCE_GROUP \
                  --image scottishsummitcontainers.azurecr.io/sampleapp:'$(Build.BuildId)'

The final stage of the pipeline now complete!

A successful Azure Container App tamopsapp has been deployed successfully!

Accessing the Application URL, will show the sample application

A simple change applied and merged, re-running the pipeline will display the latest change within your container app using az container app update

I really do think Azure Container Apps are going to awesome and used quite alot once they make their way out of Preview! Thank you for reading this blog post 🙂

GitHub Repository here with the content used above

9 comments

    1. Hi Robert,

      It’s another recommended Git repository, I use github alot also for source control with Azure DevOps Pipelines.

      That’s a huge bonus of Azure Devops, very flexible!

      Thanks

      Thomas

    1. Which stage?

      Have tested this previously before releasing blog and it works fine.

      Thanks

      Thomas

  1. I am new to Docker and Azure DevOps. Do you need to create a new container registry (step create_acr) every time you run the pipeline or can you use an existing ACR?

Leave a Reply