Deploy a Container Application to Azure App Service with Bicep

In the fast-evolving landscape of cloud computing, the ability to deploy applications swiftly and consistently is crucial. Infrastructure as Code (IaC) has become a cornerstone in achieving this, allowing teams to automate the deployment process, ensure consistency, and document every step of the infrastructure setup. One of the tools at the forefront of this movement is Bicep, a domain-specific language (DSL) for deploying Azure resources declaratively. It simplifies the definition of what a deployment should look like and makes it easier to read and write than traditional ARM templates.

Requirements

For this walkthrough, we'll be deploying a Node.js web application packaged as a container. If you're in need of a sample application, consider using "Think Alike," a multiplayer word game built with Node.js, which offers an excellent example of a real-time, interactive web application. The source code is available on GitHub:

GitHub - Latzox/Think-Alike: Think Alike is a nodejs web application. The game offers an exciting twist to classic word games. Designed for multiplayer interactions, it features real-time gameplay where players enter a virtual room, challenge each other by guessing words, and see results dynamically as the game unfolds.
Think Alike is a nodejs web application. The game offers an exciting twist to classic word games. Designed for multiplayer interactions, it features real-time gameplay where players enter a virtual…

Before we dive into the Bicep template, ensure you have the following:

  • A Docker image of the application pushed to a container registry (you can use the docker image of Think Alike if you don't have your own ready).
  • An Azure subscription where you can deploy resources.
  • Azure CLI installed on your machine for deploying the Bicep template.

Understanding the Bicep Template

Bicep templates are structured into parameters, variables, and resources. Let's break down each section of our template for deploying our application to Azure App Service.

Parameters and Variables

Parameters are inputs that you provide when deploying the template. In our case, these include the location to deploy resources, the name of the App Service, the container registry URL, the Docker image name, and its tag. We also define an environment parameter (staging or prod) to control the service tier dynamically based on the deployment context.

Variables are used to simplify expressions within the template. Here, we concatenate the Docker image path and tag to form the full Docker image reference.

param location string = resourceGroup().location
param appServiceName string = 'thinkalike'
param containerRegistry string
param dockerImageName string
param dockerImageTag string

@allowed([
  'staging'
  'prod'
])
param environment string

var dockerImage = '${containerRegistry}/${dockerImageName}:${dockerImageTag}'
var appServiceTier = environment == 'staging' ? 'F1' : 'B1'

Resources

  • App Service Plan: This defines the underlying compute resources that will host our containerized application. Depending on the environment (staging or prod), we select a different service tier (F1 for staging and B1 for production) to optimize cost and performance.
  • App Service: This is where our application lives. We specify it to run on Linux and to use a container, with the linuxFxVersion property pointing to our Docker image.
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
  name: toLower('${appServiceName}-asp')
  location: location
  kind: 'linux'
  sku: {
    name: appServiceTier
  }
  properties: {
    reserved: true
  }
}

resource appService 'Microsoft.Web/sites@2023-01-01' = {
  name: '${appServiceName}-app'
  location: location
  kind: 'app,linux,container'
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: 'DOCKER|${dockerImage}'
    }
  }
}

Deploying the template

With the Bicep template prepared, deployment is just a CLI command away. Here’s how you can deploy your application using the Azure CLI:

  1. Login to Azure CLI using az login.
  2. Set your subscription (if not set) using az account set --subscription "<Your-Subscription-ID>".
  3. Deploy the template using:
az deployment group create \
  --resource-group <YourResourceGroupName> \
  --template-file <path-to-your-bicep-file> \
  --parameters appServiceName=<yourappname> containerRegistry=<yourContainerRegistry> dockerImageName=<yourDockerImageName> dockerImageTag=<yourDockerImageTag> environment=<stagingOrProd>

Alternative Deployment Method: Bicep VS Code Extension

While the Azure CLI provides a powerful interface for deploying Bicep templates, developers seeking a more integrated experience within their coding environment can leverage the Bicep VS Code extension. This tool significantly simplifies the deployment process and enhances code management directly from the Visual Studio Code editor.

💡
The Deployment Pane is an experimental feature and still in development

Using the Deployment Pane

The Deployment Pane is an innovative and user-friendly feature. It streamlines the deployment process with a few simple clicks:

Within the Deployment Pane, you'll have the option to select the deployment scope (such as a specific resource group or subscription). You can then set all required parameters right from the interface, making it easier to tailor your deployment without modifying the Bicep file directly.

Before deploying, it's crucial to ensure that your Bicep file is free of syntax errors and configured correctly. The "Validate" function checks the syntax, providing immediate feedback. Following validation, the "What-If" feature allows you to simulate the deployment, offering a detailed report of the actions Azure Resource Manager (ARM) will take (create, modify, delete). This step is vital for understanding the impact of your deployment, ensuring there are no surprises.