Tuesday, March 2, 2021

Continuous Integration with Azure App Services and Docker Containers

Enabling continuous integration between your Azure App Services and Docker Containers is simple. Learn how.
Photo by Jason Leung on Unsplash

Following up on a previous post where we learned how to deploy our own Docker Images to Azure App Services, today we will learn how to enable continuous deployment between our App Service and our Azure Container Registry so that our ASP.NET website is automatically updated whenever a new image is pushed to our private repository.

On this post we will:

If you want to follow along, please check the previous tutorials discussing how to:

  • Build a simple ASP.NET Core image on your local Docker repository
  • Create and push a Docker Image to your own Azure Container Registry
  • Deploy Docker images to Azure App Services


As requirements, please make sure you have:

Why Continuous Deployment?

Before getting to the code, let's understand a little more about continuous deployment. Wikipedia defines it as
a software engineering approach in which software functionalities are delivered frequently through automated deployments.
And why practice CD? Still according to Wikipedia, CD is especially important because in an environment in which data-centric microservices provide the functionality, and where the microservices can be multiply instantiated, CD consists of instantiating the new version of a microservice and retiring the old version as it has drained all the requests in flight.

Reviewing our App Service

So let's start by reviewing our application. We will resume from a previous post where we explained how to deploy our Docker images to App Services. Our app looked like this:

Our App Service Panel

Here's its Azure panel:

Container Services

And here's the configuration used on the previous deployment:

Image Setup

Notice that because we're switching to continuous deployment and we'll be constantly changing the version number so sticking with v1 will no longer work. On this case, tagging our images as latest is preferred since we want automatic deployments whenever a new webapp:latest reaches the registry. As you expect, tagging an existing image is a simple process:
docker image tag webapp hildenco.azurecr.io/webapp:latest

Then we push that image again just so our repo contains a latest tag to configure our webhook:

docker image push hildenco.azurecr.io/webapp:latest

We now should now see webapp:latest in our registry:

Enabling Continuous Deployment

With the requirements in place, let's configure the necessary settings to deploy whenever a new webapp:latest reaches the registry.

Enabling App Service Continuous Deployment

To enable continuous deployment for our App Service, open your App Service -> Container Settings, set Continuous Deployment to on and the tag to latest, then save:
This operation may take a little longer than you expect because it will create a webhook with the above configuration in our registry. See the next item for more information

Reviewing the Container Registry webhook

Now go to Container Registry -> Webhooks to confirm that the previous operation created a webhook for us. As seen from the history, it was never triggered so let's push a new image to test it.

Preparing a new Version

So let's prepare another version to test if our CD works. On this step we will change the code, rebuild the image, tag it as latest and push it to our private repo.
Keep track of your versions. Images can contain multiple tags and they don't occupy any space. Treat your tags as releases. In case you want to restore or redeploy an older version, it's easier to find them by tag and by image ID.

Changing the Source Code

Firstly let's change our super-complexcode and add a link to this site in our landing page:

Rebuilding the Image

Next, we rebuild our webapp with:
docker image build . -t webapp
Then we tag it with the registry's FQDN with:
docker image tag webapp hildenco.azurecr.io/webapp:latest

Testing our Continuous Deployment

With our local image ready and tagged, let's push it to our registry and verify if the webhook was triggered.

Pushing our Image

In order to push our image, login to ACR with:
az acr login -n hildenco
Then we push it with:
docker image push hildenco.azurecr.io/webapp:latest

Reviewing the webhook

Refresh the webhook page and see that the hook executed successfully:

Reviewing the logs

And on the logs tab under Container settings, I also see that the webhook was triggered (UTC time):

Reviewing the App

Lastly, we can confirm that our awesome app was updated on the public URL:


On this post we reviewed how to do continuous integration from Docker containers into our Azure App Services using our private Azure Container Registry. Docker containers today are the standard way to build, pack and ship our applications and it's important to learn how tools such as private container registries can help us be more effective.


See Also 

About the Author

Bruno Hildenbrand      
Principal Architect, HildenCo Solutions.