Containerized Pipelines with Azure DevOps: Building, Testing, and Deploying Docker Containers to Azure

Learn how to containerize your applications using Azure DevOps, CI/CD pipelines, Docker containers, and Azure Container Registry. This article explores the benefits and demonstrates how to leverage other Azure resources for building, testing, and deploying containerized pipelines.

Containerized Pipelines with Azure DevOps: Building, Testing, and Deploying Docker Containers to Azure

Table of Contents

  1. Overview of Containerization of an Application
  2. Building a Containerised Pipeline for Node.Js Application
  3. Conclusion

As a software developer or newbie to software engineering and DevOps, you may wonder why the shift from the traditional software development approach to containers has gained immense popularity in recent years. The answer lies in the numerous benefits that containers bring to the table.

This article explores the realm of containerized pipelines with Azure DevOps, delving into their benefits and demonstrating how to dockerize your application using CI/CD pipelines on Azure DevOps while leveraging other Azure resources.

You will learn how to containerize your application, configure build, and release pipelines that deploy your container image to Azure Container Registry (ACR), and also auto-deploy to Azure App Service.

Overview of Containerization of an Application

The first question that comes to mind is to understand what containerization of an application is and why. Containerization of an application is the process of encapsulating an application, alongside its configurations, dependencies, and libraries into a self-contained unit known as a container.  A container provides a lightweight and isolated environment that allows the application to function in a consistent manner across different platforms and machines.

Containers offer unparalleled portability, allowing applications to run consistently across different environments, from local development machines to production servers. This eliminates the age-old problem of "it works on my machine" syndrome and streamlines the deployment process.

The phrase “It works on my machine” syndrome describes the challenge encountered when a software application functions as expected on one developer's machine and differently on another developer's device or environment.  It addresses this issue by creating a consistent and reproducible environment for running applications.

There are different tools used to containerize an application and the most popular is Docker.  With Docker, you can package your application with its dependencies using a Dockerfile. A Dockerfile contains a list of instructions to build an application to a container image.  These container images are standalone and executable packages of your application, typically a template for creating more instances of your application and are published to container registries such as Docker Hub or Azure Container Registry (ACR).

Benefits of Containerizing an Application.

Containerization introduces a wide range of benefits to software development aside from the case of consistency and compatibility already established as “It works on my machine syndrome”. Other benefits include:

  • Efficient Resource Utilization: Containers are lightweight and consume fewer resources than traditional virtual machines, making them ideal for modern microservices-based architectures. This allows multiple containers can run on a single host utilizing system resources optimally.
  • Isolation: Containers provide a secure and isolated environment to run applications, minimizing the risk of vulnerabilities
  • Portability: Containers can be run in any environment, providing a consistent runtime experience across different platforms. This also ensures seamless migration and deployment across platforms.

Containerized Pipeline using Azure DevOps

In the context of containerization, Azure Pipelines is a component in Azure DevOps that enables you to create and manage build and release pipelines. It allows you to define custom build and release tasks, such as building Docker images, pushing them to Container Registry, and deploying them to Azure Kubernetes Service (AKS) or Azure App Services.

It seamlessly integrates with popular containerization tools such as Docker, ensuring containerized applications are deployed consistently and efficiently across different environments. Azure pipelines also provide end-to-end containerization support and lots of benefits, including:

  • Flexibility: Azure Pipelines supports a range of containerization scenarios, including multi-container applications, Docker Compose, and Kubernetes.
  • Security: Azure Pipelines provides built-in security features, such as image scanning and vulnerability assessments, ensuring that containers are secure and compliant.
  • Automation: Azure Pipelines automates the entire containerization process, reducing manual errors and improving consistency.

Building a Containerized Pipeline for Node.js Application

In this section, you will delve into exploring containerization using Azure DevOps Pipelines. This will cover a step-by-step demonstration of building a containerized pipeline specifically designed for Node.js applications.  By leveraging the power of Docker and Azure Pipelines, you will set up a seamless CI/CD pipeline to build and containerize a Node.js app and deploy this container image to AKS and also App Service.

To follow on, you will need to have the following:

  • Azure Account with an active subscription
  • Azure DevOps Account
  • Git installed on your machine.
  • VS Code (Code Editor)

Creating a Project on Azure DevOps

  • Login to dev.azure.com, you will be signed into an existing organization, or you can create a new one if you are signing in for the first time. For details on creating a new organization and project see previous article link
  • Click on New Project or use an existing one:
Create New Project - Azure DevOps
Create New Project - Azure DevOps
  • This opens a dialog window as shown below. Enter a project name and click the Create button:
Create New Project - Azure DevOps
Create New Project - Azure DevOps

Setting up your Node.js Application in Azure Repo

Repos in Azure DevOps is a repository for storing and managing your source code. It supports Git and Team Foundation Version Control (TFVC).

Git is distributed version control system that manages repositories, that offers features such as branching, merging, and pull requests. TFVC, on the other hand, is a centralized version control system that uses a centralized server to store files.

Each project in Azure Dev comes with a default Repo, you will import your project files to this repo from your PC.

  • Click Repos located at the left menu on your project dashboard, this opens the overview for Repos with options on how to proceed.
  • Click the Clone in VS Code button:
Clone Azure Repo to VS Code
Clone Azure Repo to VS Code
  • This opens VS Code on your machine and a window to allow you to select the folder to clone your project to.
  • You can choose any folder or create a new one.  Now, you have the Azure Repo cloned to our PC, you will proceed to clone a sample NodeJS Project:
Clone Azure Repo to VS Code

Clone Azure Repo to VS Code

  • On VS Code, click on Terminal from the top menu items to open a new terminal. On the new terminal window run the command below to clone the sample project:
git clone <https://github.com/Azure-Samples/nodejs-docs-hello-world.git>
Clone Azure Repo to VS Code
Clone Azure Repo to VS Code
  • Open the project folder node-docs-hello-world and create a file with the name dockerfile and no file extension. Paste the following code inside the dockerfile:
# Use the official Node.js image as the base image
FROM node:14-alpine

# Set the working directory in the container
WORKDIR /app

# Copy the package.json and package-lock.json files to the container
COPY package*.json ./

# Install the dependencies
RUN npm install

# Copy the application source code to the container
COPY . .

# Expose a port for the application
EXPOSE 3000

# Define the command to run the application
CMD ["node", "app.js"]

This dockerfile contains instructions that encapsulate your application and its dependencies and outputs them as a container image during pipeline build.

  • After adding dockerfile, your project folder should look the same as the image below:
Added Dockerfile to Node.js App - VS Code
Added Dockerfile to Node.js App - VS Code
  • Open the terminal again and run the following git command one after the other to push this update to Azure Repos:
# Change into the cloned directory
cd nodejs-docs-hello-world

# Add all new files and commit
git add .
git commit -m "added dockerfile"

# Remove existing remote origin from the cloned folder 
git remote remove origin

# Add your Azure Repo's origin and push
git remote add origin <https://[email protected]/Techruptblogger/containerised_pipeline/_git/containerised_pipeline>
git push -u origin --all

These git commands add all files to your local machine and commit all changes made. Since the project is cloned, this implies that it has an origin, you will have to remove the first origin and replace it with the origin from your project repo and lastly push all files to Azure Repo. Find the instructions to update the URL in the next step.

  • To get the link to your Azure repo origin, open Azure DevOps project click on your empty Repo > Files and scroll to the “Push an existing repository …” section as shown below:
Locate Azure Repo Origin - Azure DevOps
Locate Azure Repo Origin - Azure DevOps
  • On successfully running the script, your files will be pushed to Azure Repos:
Pushed File from VS code to Azure Repos - Azure DevOps
Pushed File from VS code to Azure Repos - Azure DevOps

You have successfully pushed all project files to Azure Repo. You will need to set up other resources needed for this Demo such as setting up Azure App Service and Azure Container.

Creating an Azure App Service on Azure Portal

  • Open portal.azure.com and search for App Service, ensure to select the Publish option as the code option as Docker Container.  Fill in other option and click Review + Create:
Create App Service for Container - Azure Portal
Create App Service for Container - Azure Portal
  • This will take a few minutes to complete. On completion open the resource, this should look the same as shown below:
Create App Service for Container - Azure Portal
Create App Service for Container - Azure Portal

Create an Azure Container Registry (ACR) on Azure Portal

  • On Azure Portal Search for Container Registry and create a Container Registry. Fill in the required input marked asterisk and click Review + Create:
Create Container registry - Azure Portal
Create Container registry - Azure Portal

This will take a few minutes to set up your container registry. Below is an overview of the Techrupts container registry created:

ACR Overview - Azure Portal
ACR Overview - Azure Portal

Set up Managed Identity Access from Web App to Container Registry

Setting up manage identity simplifies the process of managing credentials and authentication by allowing resources to authenticate securely with other Azure services and resources. To enable seamless flow between ACR and App Service, you need to set up managed identity access.

  • Open the newly created App Service (techrupsdemo) and navigate to System Assign under Identity on the left menu. Toggle the Status to enable it and click Save:
Enable System Assigned Identity - Azure Portal
Enable System Assigned Identity - Azure Portal

By turning this on, Azure assigned an identity to App Service, which enables it to authenticate itself with Azure AD and access other resources.

  • On Container Registry, locate Access Control (IAM) on the left menu. Click +Add and select Add Role Assignment:
Set Up IAM Access Control for ACR Pul- Azure Portal
Set Up IAM Access Control for ACR Pul- Azure Portal
  • On the Add role assignment window, select ACR Pull and click Next:
Set Up IAM Access Control for ACR Pul- Azure Portal
Set Up IAM Access Control for ACR Pul- Azure Portal
  • On the Members tab of Add role assignment window, click + Select members to add the ACR pull role to App Service managed identity:
Set Up IAM Access Control for ACR Pul- Azure Portal
Set Up IAM Access Control for ACR Pul- Azure Portal
  • Search and select the App Service name from the list and click Select to save:
Set Up IAM Access Control for ACR Pul- Azure Portal
Set Up IAM Access Control for ACR Pul- Azure Portal
  • You will be taken back to the Members tab. Click Review + assign and finish the role assignment:
Set Up IAM Access Control for ACR Pul- Azure Portal
Set Up IAM Access Control for ACR Pul- Azure Portal
  • To enable access credentials for the Container Registry, navigate to Access Keys and toggle Admin user to Enabled. Keep these details handy as you will need this information to authenticate your pipeline later:
Enable Access to the container registry.
Enable Access to the container registry.

Setting up Service Connection on Azure DevOps for Azure Resources

Creating a service connection provides a secure way to establish a connection between your pipeline and external services, in this case, Azure Subscription.

By adding a service connection, your pipeline can securely access these external services during the pipeline execution. If you have this set up proceed already, skip to the next step.

  • Open your project on the Azure DevOps portal, and Click on Project Settings:
  • Navigate to the Service Connections under Pipelines section and click on the Create Service Connections:
Untitled
  • On the New service connection window, select Azure Resource Manager and click Next:
Set Up New Service Connection - Azure DevOps
  • Select Service Principal (automatic) and click Next:
Set Up New Service Connection - Azure DevOps

Set Up New Service Connection - Azure DevOps

The next screen requires you to authenticate to Azure. Complete the authentication so this can load your active subscription on your account on the next screen.

  • Select the Subscription and Resource group associated with your Azure resources. Enter the Service Connection name and check the Security box for Grant access permission... Click Save once done:
Set Up New Service Connection - Azure DevOps

Set Up New Service Connection - Azure DevOps

Set up Azure DevOps CI/CD Pipelines

Now you have your project files on Azure Repo, you need to set up a pipeline to build the image and publish it to Azure Container Registry (ACR) and also a release pipeline to deploy an image to Azure Web App. This will be achieved by configuring a build pipeline and also a release pipeline.

Configuring a Build Pipeline to Build the Container Image

  • Inside the Azure DevOps portal, navigate to your project and click Create Pipelines under Pipelines side menu:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • Select Azure Repo Git under Where is your Code option:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • Select your repository where you have the Node.js App:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • Select the 2nd docker option- Build and push an Image to Azure Container Registry from the list under Configure tab:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • The following window displays the auto generated Yml file (azure-pipelines.yml) that builds your container image and publishes it to ACR, you may want to edit and make changes to the file otherwise, click Save and Run:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • Enter the commit message or use the default, this is needed as a comment to commit the build template file to your project repo, then click Save and Run:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • This opens a few sub-windows, the first window requires your subscription, select the same subscription where you have your resources and click Continue:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • Select the container registry, enter a name for your new image, and click Validate and Configure:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • This returns to the review window, click the Save and Run button again to complete the process and run the pipeline:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps

Once the pipeline execution is started, the build summary page is displayed. This is to enable you to monitor to your pipeline progress.

  • To confirm your pipeline was successful, you will see the job status as Success:
Configuring a build pipeline on Azure DevOps
Configuring a build pipeline on Azure DevOps
  • Navigate to Azure portal, open Container Registry, navigate to Repositories, and confirm the image is published. Take note of the Tag as this will be referenced later:
Published Image to Container Registry from Azure Pipelines
Published Image to Container Registry from Azure Pipelines

Configuring Release Pipeline for Deployment

Now you have successfully built an image and published it to ACR, you configure a release pipeline to pull this image to a web app (App Service)

  • Inside the Azure DevOps projects under the Pipelines menu, click Releases and New Pipeline to create a new release pipeline:
Configure a Release pipeline to deploy containerized App to App Service
Configure a Release pipeline to deploy containerized App to App Service
  • On the Select a template window, select Azure App Service Deployment and click Apply:
Release Pipeline set up on Azure DevOps
Release Pipeline set up on Azure DevOps
  • Enter a name for the pipeline stage and click on the Stage box to expand the settings:
Release Pipeline set up on Azure DevOps
Release Pipeline set up on Azure DevOps
  • On the Pipeline stage settings, select your Subscription and click Authorize:
Release Pipeline set up on Azure DevOps
Release Pipeline set up on Azure DevOps
  • Fill out the following information and click Save:
  • On the App service type, select Web App for Containers
  • Select the App Service name created earlier as the destination resource.
  • On Registry or Namespace, enter <registryname>azurecr.io. <registryname> should be changed to the name of your container registry.
  • On Repository, enter the Image name of your choice:
Release Pipeline set up on Azure DevOps
Release Pipeline set up on Azure DevOps
  • Click on the Deploy Azure App Service task, you will notice every other option is auto-filled and greyed out except for Tag. Enter your image tag number as seen on your image repository (Review Configuring a Build Pipeline to build the container image)
  • Expand the Application and Configuration Settings and click the three dots beside the App Service setting:
Release Pipeline set up on Azure DevOps
Release Pipeline set up on Azure DevOps
  • This opens the App Settings window, add these configurations and click Ok.
  • WEBSITE_PORT “3000” (ensure this is the same port configured on your dockerfile)
  • DOCKER_REGISTRY_SERVER_USERNAME <enter credential as send on container registry admin access>
  • DOCKET_REGISTRY_SERVER_PASSWORD <enter credential as send on container registry admin access>
App Settings on Azure DevOps Pipelines
App Settings on Azure DevOps Pipelines
  • Once saved, the Create Release button will be active, click Create Release:
Create Release - Azure DevOps Pipelines
Create Release - Azure DevOps Pipelines
  • On the Create a new release window, ensure to check the release box to highlight a blue color and click Create. This changes the stage from Manual to automated:
Create Release - Azure DevOps Pipelines
Create Release - Azure DevOps Pipelines

Validating Deployment Progress

To confirm the status of your Release Pipeline, you have to open the release and locate logs.

  • Click on Releases-1 under the Releases:
Release Pipeline Progress - Azure DevOps Pipelines
Release Pipeline Progress - Azure DevOps Pipelines
  • As the release and stages box opens, click on Logs in the Stages column:
Release Pipeline Progress - Azure DevOps Pipelines
Release Pipeline Progress - Azure DevOps Pipelines
  • This opens the deployment progress. You can monitor the progress of this release and ensure it deploys to App Service without any error:
Release Pipeline Progress - Azure DevOps Pipelines
Release Pipeline Progress - Azure DevOps Pipelines
  • On completion, navigate to App Service URL, and you will see a simple Hello world displayed:
Successful Deployment  to Azure App Service
Successful Deployment to Azure App Service

Conclusion

Containerized pipelines with Azure DevOps offer a transformative and flexible approach to application deployment. By leveraging the benefits of containerization, developers can achieve improved portability, scalability, and consistency across environments.

This article provided a step-by-step demo of building a containerized pipeline for a Node.js application using Azure DevOps. From project setup to configuring CI/CD pipelines and monitoring deployment progress, it covered the essential components for successful deployments. Embracing containerized pipelines with Azure DevOps empowers development teams to streamline workflows and deliver high-quality applications efficiently.