Build, Run, and Continuously Deploy Docker Containers on Azure App Service

If you're thinking about investing your time to pick up new skills, you can't go wrong with learning how to build, run, and manage containers.

That's probably not a big surprise. Based on all the excitement, headlines, and success stories coming out of tech news every day, there’s no doubt we’ll see even more container adoption going forward. But, it’s still very early in the game. And that means there’s a massive opportunity for those who embrace this new approach to building modern applications.

My goal with this tutorial is to hopefully spark your interest in this topic or give you some new ideas to try out on your own. I’ll show you a quick and easy way to store and run your container images on Microsoft’s Azure platform.

We’ll take a look at how to build a container image locally, push that image to the Azure Container Registry, and then run and continuously deploy updates to that container using Azure Web App for Containers. It's a great way to run a single container for a web application.

We’ll keep things simple, but practical. And, if you want to follow along, all you'll need is Git and Docker Desktop installed locally, along with an Azure account.

Building the Azure Container Registry (ACR) Resource

Container images provide the foundation for applications running inside Docker containers. You can think of an image as an executable package that includes everything you need to run an application. Your container images include application code, the runtime environment, libraries, configuration files, and environment variables. Containers that you spin up to power an application are merely a running instance of a container image.

Container images live in public or private container registries, and servers running the Docker engine download those images to start and run containers. The default container registry for Docker containers is, which offers over 100,000 container images from ISVs, open-source projects, and community contributors. You can use this service to store your images in public or private repositories.

Microsoft also offers the Azure Container Registry (ACR), which is a managed Docker registry service based on the open-source Docker Registry 2.0 platform.

Using ACR for container deployments allows you to store your custom container images privately in the Azure cloud. ACR natively integrates with multiple Azure services, and teams can use ACR tasks to automate deployments when building new images, or when code is committed to version control. ACR also provides a low-latency endpoint to pull images from when your Docker hosts are running in the Azure cloud.

For this tutorial, we’re going to provision a new ACR instance. We’ll build a custom Docker image and push it to ACR so we can use it later with Azure Web App for containers.

In the Azure portal, select Create a resource, select Containers in the Azure Marketplace, and choose Container Registry.

Figure 1. Creating an ACR Resource.

Enter a globally unique, DNS-compliant hostname for your registry under the namespace. Set the destination resource group and make sure you enable the option for admin user and click on Create.

Once provisioning is complete, navigate to your ACR resource in the portal and select Access Keys under the settings section. Here you will see your login server, admin username, and passwords.

Figure 2. Retrieving the ACR Credentials.

Finally, fire up a terminal and use the docker login command to authenticate to ACR and validate the credentials.

Figure 3. Logging into the ACR.

You should see a message that says “login succeeded” as shown in Figure 3.

Cloning the Sample Node & Express Application

Next, we’re ready to package up an application into a container image. For this example, we’ll use a bare bones Node.js and Express application from my Github account. The app is really basic and simply returns a “hello world” message when you visit the web application.

Open a terminal or command prompt and switch to a directory where you want to store the source code locally. Use the following command to clone the repo:

git clone

After you've cloned the repo, switch into the application directory:

cd node-docker-demo/

Inside the local repo you'll see the following set of files and folders:

├── Dockerfile
  ├── app.js
  ├── config.js
  ├── package-lock.json
  ├── package.json
  └── test
  └── index_test.js

The main thing to focus on here is the Dockerfile included with the application. This will give Docker all the instructions to build our container image. Open the Dockerfile in a text editor to review the commands. You'll see something like the output in Figure 4.

FROM node:alpine
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "start"]
view raw Dockerfile hosted with ❤ by GitHub
Figure 4. Reviewing the Dockerfile.

The commands in the Dockerfile will be used to build the image locally before we push it to ACR. Let's break it down line by line.

  • Line 1: The FROM command defines the base container image. In this case, we'll use the official Node.js image available in the Docker Hub. Notice we're not explicitly referencing a container registry for this image. This means we'll pull down the Node.js container image from the default container registry (Docker Hub). Also note that the image uses an alpine tag. This means we'll use the Node.js container image based on Alpine Linux, which is a Linux distro designed for security and resource efficiency. It will allow us to keep the container image very small at less than 90 MB in size.
  • Line 3: The WORKDIR command sets the working directory and is where we'll store the applicaiton code. If the path indicated doesn't exist it will get created during the build process.
  • Line 5: The COPY command will be used during the build process to add the package.json and package-lock.json files to the working directory. Note that, instead of copying the entire application at this stage, we are only copying the package*.json files. This allows us to take advantage of cached Docker layers to improve our development workflow, which you can read about here.
  • Line 6: Next, the RUN command is used to execute npm install which will ensure our application dependencies are included within the container image.
  • Line 7: The COPY command is used to copy the application source files into the working directory.
  • Line 9: Finally, CMD defines the default command to execute when the container starts. In this case, npm start will run the start script defined in the package.json file to get our node server up and running.

Now that we understand what will be included in our container image, we're ready to run a build.

Building the Container Image

Head back over to the command-line. Make sure your context is set to the root of the application. You should be in the same directory as the Dockerfile. Use the docker build command to create your container image.

docker build -t <YOUR REGISTRY NAME> .

This command will tell Docker to build your image using the Dockerfile in the current directory. It will also tag your image with your ACR repository name, an image name, and version set to latest to indicate that this image is the current version of the application.

Since the registry name is included in the image tag, the Docker client will intuitively know where to send the image when we run a push in the next step.

Pushing the Image to ACR

Since we already logged in using docker login, all that's left to do is push the image up to ACR using the following syntax.

docker push <YOUR REGISTRY NAME>

After the command completes successfully, you can head back to the Azure portal to verify that your image is now available in ACR.

Figure 5. Reviewing the image in ACR.
Building the Web App Resource

With the image available in ACR, we're ready to build a Web App resource that can host the application. In the Azure portal, select Create a resource, select Web in the Azure Marketplace, and choose Web App.

Figure 6. Creating the Web App Resource.

Enter a globally unique, DNS-compliant hostname for your web app under the namespace. Set the destination resource group and choose Linux as the OS. Make sure the publish settings are configured to use a container as shown in Figure 6. You'll be able to browse and find your custom container image in ACR. Click on Apply and Create.

Open a web browser and navigate to the URL for your new Azure Web App. You should see "Hello World!" on the home page.

Figure 7. Testing the Web App.

Now that we have the app up and running we can setup continuous deployment.

Enabling and Validating Continuous Deployment

Navigate to your Web App resource in the Azure portal. Select Container settings as shown in Figure 8.

Figure 8. Updating the Web App.

Switch Continuous Deployment to On and click on Save.

This will create an ACR webhook behind the scenes. Anytime we push an updated image to ACR it will trigger a deployment in Azure App Service. This means we can update and rebuild our image locally, push it back to ACR, and the website will be updated without us having to do anything else. You'll see the webhook in the same resource group as your web app in the Azure portal.

Figure 9. Reviewing the Web Hook.

Now that continuous deployment is enabled, we can test out. Fire up your code editor and open the app.js file in the root of the application that we cloned earlier. Modify line 7 to return a new message. For this example, I'll update the code to return "Hello World v2!" when a user visits the page.

const config = require('./config');
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World v2!');
app.listen(config.port, () => {
console.log(`Server started on port ${config.port}`);
view raw app.js hosted with ❤ by GitHub
Figure 10. Updating the app.js file.

Once the code has been updated, rebuild the container image:

docker build -t <YOUR REGISTRY NAME> .

Then push the new container image to ACR:

docker push <YOUR REGISTRY NAME>

The push will trigger the webhook.

Figure 11. Reviewing the Web Hook History.

Then we can visit our web app and see that it's serving the new version of the application.

Figure 12. Validating the Deployment.

Isn't that awesome? This is a really slick solution for those who want to streamline the deployment process for single container-based web apps.

Where to go from here

There's so much more when it comes to running Docker containers on Azure. Check out some of these resources to help you get started.

Subscribe to the CloudSkills Weekly Newsletter

Get exclusive access to special trainings, updates on industry trends, and tips on how to advance your career in the tech industry.