Continuous deployment to Azure Container Apps with Azure DevOps

Photo of author

Dan Rios

5 min read


Deploying to Azure Container Apps with Azure DevOps and want a quick start reference to get going?

I’ll detail how you can quick start continuous deployment to your Azure Container App revision in single revision mode with Azure DevOps, featuring a quick start YAML pipeline that will build your container, publish to Azure Container Registry and lastly deploy it to the Container App itself!

Multi-revision scope deployments are not in scope for this example.

What are Azure Container Apps?

Azure Container Apps is a fully managed Kubernetes-based application platform that helps you deploy apps from code or containers without orchestrating complex infrastructure

Azure Container Apps | Microsoft Azure

My personal take is that Azure Container Apps are a fantastic way to get into microservices in Azure without the administration overhead of full blown AKS (Azure Kubernetes Service) which can be quite overwhelming without a dedicated, knowledgeable Kubernetes engineers/admins team behind it.

Azure Container Apps are simple, easy to pickup and quite cost effective, especially as you can scale to zero incurring no consumption charges.

Single revision mode with zero downtime deployments 🚀

In Azure Container Apps using single revision mode, we can deploy using the above method for zero downtime deployments. Each revision is considered a ‘snapshot’ of your container application.

When we deploy the Azure Container App it creates a new revision in the backend, and undergoes the relevant readiness and start up checks. Once it is successfully provisioned, and only when it is successful, will it be promoted and activated – this is when traffic will start flowing into the new revision.

The previous is deprovisioned automatically for you. If the provisioning of the new revision fails then it won’t proceed, so you have confidence only healthy container apps will be promoted to live.

Here’s an example of this process:

New revision is deployed from new ACR (Azure Container Registry) image:

Activating Azure Container App

Once successfully provisioned and running, the previous revision is deprovisioned (note the traffic values).

Azure Container App deprovisioning

Lastly, the deprovisioned app moves to the inactive tab, giving opportunity to re-active should you require.

Azure Container App inactive revision

Azure DevOps Prerequisites 🧙‍♂️

There’s some pre-reqs you’ll need to have setup in your Azure DevOps project for this pipeline example to work:

  1. Docker registry service connection scoped to your Azure Container Registry in Azure DevOps
  2. Azure resource manager connection scoped down to your Azure Container App Resource Group (Or setup a managed identity for the connection instead) in Azure DevOps
  3. an Azure DevOps environment setup in your Azure DevOps Project
  4. You’re already somewhat familiar with fundamentals of Azure DevOps & Git

I’ll assume that you have already deployed your Azure Container App environment & App with an Azure Container Registry.

Azure DevOps Pipeline – Example

Here’s a YAML build & deploy example that will build the dockerfile in your Azure DevOps GIT repository, before deploying it to your Azure Container App by creating a new revision before promoting this.

If you’re unfamiliar with creating a new Azure DevOps pipeline – it’s nice and simple:

  1. Create a new file in your repository, e.g. ‘aca-deploy-pipeline.yaml‘ and copy/paste the example code snippet from below amending the necessary values
  2. Commit the file to main branch (or to your feature branch, then create a pull-request to merge into main branch)
  3. In your Azure DevOps project go to Pipelines > New Pipeline > Azure Repos Git > Existing file > Select your .yaml file from the drop down > Click the blue button next to Run to Save

Amend the variables to the resource names of your environment.

– main
– '**/*.yaml'
# Docker build & push connection
– name: dockerServiceConnection
# ADO ARM Connection
– name: azureServiceConnection
# Resource Group name where the ACA is deployed to
– name: aca-rg
value: 'YOUR-ACA-RG'
# Azure Container App name within your ACA enviornment
– name: aca-name
value: 'YOUR-ACA-NAME'
– name: aca-acr
value: ''
# Azure Container Registry repository where the image resides
– name: aca-repo
value: 'YOUR-ACR-REPO'
# Azure DevOps Enviornment for deployment history + approvals
– name: ado-env
# Build tag based on ADO pipeline Build Id
– name: tag
value: '$(Build.BuildId)'
vmImage: ubuntu-latest
– stage: Build
displayName: Build & Push Docker Image
– job: BuildDocker
displayName: Build & Push Docker Image
– task: Docker@2
displayName: Build and push an image to container registry
command: buildAndPush
repository: $(aca-repo)
dockerfile: 'Dockerfile' # Change if your Dockerfile doesn't sit in root of the repo
containerRegistry: $(dockerServiceConnection)
tags: |
– stage: Deploy
displayName: Deploy ACA
dependsOn: Build
– deployment: ACADeploy
displayName: Deploy Azure Container App
environment: $(ado-env)
– task: AzureCLI@2
displayName: Updating ACA image
azureSubscription: $(azureServiceConnection)
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
az containerapp update -n $(aca-name) -g $(aca-rg) –image $(aca-acr)/$(aca-repo):$(Build.BuildId)

Build Process – Docker build, tagging and Azure Container Registry 🏗️

When changes are made to our main branch (code, or dockerfile) it’ll trigger the pipeline to perform a docker build and push to the Azure Container Registry. This will publish a new image with the build Id as the tag from the Azure DevOps Pipeline run.

It’s important that you do avoid using the latest tag when tagging your images.

Not only is it not best practice (see semantic versioning for the gold standard of how to tag versions), but it will cause issues with not being able to bring up new revisions cleanly, as the tag is the same every time you deploy.

It will further make auditing and version history problematic and complex. In addition to causing issues with Defender for Cloud scans, where you will have to go into the Azure CLI and explore ACR manifest Ids to remove old manifests that may have vulnerabilities.

Container Registry

After a successful build stage, we’ll be able to see in the Azure Container Registry new images with the build id from the Azure DevOps Pipeline build runs.

Deployment Process – Azure Container App 🚀

Once the build stage is completed successfully. The deployment stage will proceed in Azure DevOps. If you have setup approvals on your Azure DevOps environment (highly recommended) this is where it’ll prompt if you want to deploy to your production Azure Container App.

This deployment stage is quite simple, we’re just using the Azure CLI “az containerapp update” to update our existing Azure Container App with a new revision, using our build image from the ACR in the previous stage.

The reason I personally use the Azure CLI over the built-in Azure DevOps task is simply because I found it to be a bit problematic for my use case, it’s still quite new and there’s some issues I had with it.

Your mileage may vary, so by all means give it a shot – the documentation linked above is great and will guide you through what you need.

Conclusion 🏁

That’s it. A fairly simple pipeline to get started with continuously deploying to your existing Azure Container App using single revision mode.

My experience with Azure Container Apps has been fantastic. I’ve yet to deep dive into the Kubernetes world and for customers Azure Container Apps really takes away a lot of the management and administrative overhead that can create a ton of TOIL.

I love how it’s well priced, and can scale to 0 so it can be very cost effective.

I hope this guide and post insights others going down this path. Are you using ACA, what’s your thoughts? Let me know!

Leave a comment

Skip to content