No results for

TutorialsLast Updated May 1, 20257 min read

Continuous deployment for Azure web apps

Fikayo Adepoju

Fullstack Developer and Tech Author

Developer D sits at a desk working on an intermediate-level project.

Over the past ten years, Azure has become one of the most prominent cloud computing platforms available, rivaled only by AWS. Part of Microsoft’s suite of Azure services, Azure web apps provide a packaged environment for hosting web applications built in many languages. Because this environment is fully managed by Azure, developers have limited options for control. One of the limitations involves the process of deploying applications to the hosting environment, which allows only for the connection of a remote repository while Azure takes over the whole deployment process.

In this tutorial, you will learn how to build a custom pipeline into the deployment workflow of an Azure web application, regaining full control of the process so you can run tests before deployment.

Prerequisites

To follow this post, a few things are required:

  1. Node.js installed on your system (version >= 20.0.0)
  2. An Azure account
  3. A CircleCI account
  4. A GitHub account

With all these installed and set up, it is time to begin the tutorial.

First, here is the strategy you will use to create the custom deployment pipeline to Azure:

  • Push your project to a remote GitHub repository
  • Configure CircleCI to run tests automatically on every push to the main branch
  • If the tests pass, use the Azure CLI to deploy the application to Azure Web App via az webapp deploy
  • This gives us full control of the CI/CD workflow while keeping deployments fast and reliable.

Creating the Azure web app

Go to your Azure Portal dashboard and click Create a resource to create a new service instance. From the Popular list, click Web App. You can also use the search box.

Create web app - Azure

On the Create Web App page, select your Azure subscription and a resource group. Resource groups are used to organize and manage related Azure services. You can choose an existing group or create a new one.

Next, in the Instance Details section, enter a name for your web app — for example, node-cd-api. Azure will automatically generate a default hostname in the format:

https://<AppName>-<HASH>.<Region>.azurewebsites.net
Copy to clipboard

So if your app name is node-cd-api and it’s deployed to East US, the resulting URL might look like:

https://node-cd-api-hbdufzepe6g5febr.eastus-01.azurewebsites.net
Copy to clipboard

This new format helps prevent subdomain takeover by appending a unique hash and region to your app name.

Fill in the next set of options:

  • Publish: Code
  • Runtime stack: Node 20 LTS (you will be hosting a Node.js application)
  • Operating System: Linux
  • Region: Select the one closest to your location (or any you prefer). This tutorial uses East US.

Create web app options - Azure

Leave the default for the rest of the options.

Click Review + create. On the Review page, confirm the option you selected, then click Create. Azure will begin setting up the web app environment. When the process is done, you will be directed to your web app dashboard. If not, click Go to Resource.

Setting up the Node.js project

Next, clone the project you want to test and deploy to the web app you just created. For this tutorial, you are using a basic Node.js API with two endpoints:

  • GET / returns a simple message confirming the app is running

  • GET /todos returns an array of todo objects

The project also includes a test suite to validate these endpoints.

Choose a location on your system and run:

git clone --single-branch --branch base-project https://github.com/CIRCLECI-GWP/node-cd-api.git
Copy to clipboard

Once cloned, navigate into the project directory and install dependencies:

cd node-cd-api
npm install
Copy to clipboard

You can now start the application using:

By default, the app runs at http://localhost:3000. Once it’s up, try visiting the following URLs in your browser:

  • http://localhost:3000/ returns: "App is up and running!"

  • http://localhost:3000/todos returns the list of todos in JSON format

Todos endpoint - Node app

Stop the application at the command line using Ctrl + C.

Run the application tests:

The output in your CLI will show that the tests have passed.


> cd-nodejs-azure-vm@1.0.0 test
> jest

 PASS  __tests__/apiTest.js
  ✓ Fetch Todos (16 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.325 s, estimated 6 s
Ran all test suites.
Copy to clipboard

Creating an Azure service principal account

Microsoft Azure recommends using a service principal account for accessing Azure resources in automated or non-interactive scenarios like CI/CD pipelines.

A service principal is a special identity created for use by applications, scripts, or tools rather than a human user, allowing secure access to Azure resources via the CLI.

In this tutorial, you will create a service principal that CircleCI will use to authenticate and deploy the application securely from the pipeline.

To create one, run the following command:

az ad sp create-for-rbac --name "circleci-service-account" --role contributor \
 --scopes /subscriptions/<your-subscription-id>
Copy to clipboard

Replace <your-subscription-id> with your Azure subscription ID.

Note: If you don’t remember your Azure Subscription ID, retrieve it with:

az account list --output table
Copy to clipboard

Copy the SubscriptionId of the subscription you want to use.

Azure returns credentials like:

{
  "appId": "xxxxx",
  "password": "xxxxx",
  "tenant": "xxxxx"
}
Copy to clipboard

Take note of these, you’ll use them as environment variables in CircleCI. The appId is the Client ID, the password is the Client Secret, and the tenant is the Tenant ID.

These credentials will allow CircleCI to deploy to your Azure Web App securely using the Azure CLI.

Setting up CI/CD with CircleCI

Create a .circleci/config.yml file in the root of your project and add the following configuration script to it:

version: 2.1

orbs:
  azure-cli: circleci/azure-cli@1.3.2
  node: circleci/node@7.1.0

jobs:
  build-and-test:
    executor: node/default
    steps:
      - checkout
      - run:
          name: Install dependencies
          command: npm install
      - run:
          name: Run tests
          command: npm test

  deploy:
    executor: node/default
    steps:
      - checkout

      - azure-cli/install

      - azure-cli/login-with-service-principal:
          azure-sp: AZURE_CLIENT_ID
          azure-sp-password: AZURE_CLIENT_SECRET
          azure-sp-tenant: AZURE_TENANT_ID

      - run:
          name: Set subscription
          command: |
            az account set --subscription $AZURE_SUBSCRIPTION_ID

      - run:
          name: Zip app and deploy
          command: |
            zip -r app.zip . -x "*.git*" "node_modules/*"
            az webapp deploy \
              --resource-group $AZURE_RG \
              --name $AZURE_APP_NAME \
              --src-path app.zip \
              --type zip

workflows:
  version: 2
  build-test-and-deploy:
    jobs:
      - build-and-test
      - deploy:
          requires:
            - build-and-test
Copy to clipboard

In the configuration above, CircleCI automates the testing and deployment of the Node.js web application to Azure Web App. The build-and-test job runs in a Node.js Docker environment, installs the project dependencies using npm install, and executes the test suite with npm test. Once tests pass, the deploy job takes over to handle deployment. It checks out the project code, installs the Azure CLI, and logs into Azure using a service principal with credentials stored in environment variables. After setting the active Azure subscription, it zips the application (excluding unnecessary files) and deploys it using the az webapp deploy command. The workflow ensures that deployment only happens if the test job succeeds, enabling a secure and efficient CI/CD pipeline.

Next, run the rm -rf .git command at the root of the project to remove any contained .git history. Push the project to GitHub. Make sure that this is the GitHub account connected to your CircleCI account.

Now, go to the Projects page on the CircleCI dashboard. Select the associated GitHub account to add the project and click Set Up Project. You will be prompted to enter the branch housing your configuration file. CircleCI will detect the .circleci/config.yml file and start building the project.

CircleCI Project Setup

This will trigger the pipeline, but it will fail because you haven’t set up the environment variables for the required credentials in CircleCI yet:

CircleCI pipeline failure

Setting up environment variables in CircleCI

Head over to your project settings on the CircleCI dashboard and navigate to the Environment Variables section. Here, you’ll define the values CircleCI needs to authenticate with Azure and deploy your app.

Add the following environment variables:

  • AZURE_CLIENT_ID – the App ID of your service principal

  • AZURE_CLIENT_SECRET – the password (secret) of your service principal

  • AZURE_TENANT_ID – the tenant ID of your Azure Active Directory

  • AZURE_SUBSCRIPTION_ID – your Azure subscription ID

  • AZURE_RG – the name of the resource group containing your web app

  • AZURE_APP_NAME – the name of your Azure Web App

CircleCI environment variables

Once these are in place, trigger the pipeline again by pushing a commit or re-running the last job. If everything is correctly configured, the pipeline should pass and deploy your app to Azure.

CircleCI pipeline success

To retrieve the deployed app’s URL, you can run:


az webapp show \
  --resource-group $AZURE_RG \
  --name $AZURE_APP_NAME \
  --query defaultHostName \
  --output tsv

Copy to clipboard

This will return a URL like:

https://node-cd-api-hbdufzepe6g5febr.eastus-01.azurewebsites.net/
Copy to clipboard

Deployed app URL

You can now visit your live application. Try editing the todos.js file to add a new todo item, push your changes to the main branch, and watch as CircleCI runs tests and redeploys the updated app automatically.

Conclusion

DevOps is all about designing, automating, and integrating solutions to deliver software reliably and efficiently. In this tutorial, you combined the power of CircleCI’s flexible CI/CD pipelines with the scalability of Azure Web Apps to create a seamless deployment workflow. Whether you’re a developer, architect, or engineer, this approach helps you ship updates faster while keeping control over your deployment process.


Fikayo Adepoju is a LinkedIn Learning (Lynda.com) Author, Full-stack developer, technical writer, and tech content creator proficient in Web and Mobile technologies and DevOps with over 10 years experience developing scalable distributed applications. With over 40 articles written for CircleCI, Twilio, Auth0, and The New Stack blogs, and also on his personal Medium page, he loves to share his knowledge to as many developers as would benefit from it. You can also check out his video courses on Udemy.

Copy to clipboard