Deploying a Serverless Web App with Bicep: A Comprehensive Guide
Written on
Chapter 1: Introduction to Serverless Applications
The aim of this article is to guide you through the process of deploying a serverless web application utilizing Bicep Language. Azure Bicep is a specialized language that employs a declarative syntax to facilitate the deployment of Azure resources. It serves as an abstraction over Azure Resource Manager (ARM) templates, allowing for the definition of Azure resources through declarative Infrastructure as Code.
Prerequisites
Before we begin, ensure you have the following:
- An active Azure account (you can create one for free).
- A resource group within your Azure subscription.
- A user-assigned managed identity (MSI) with Contributor permissions, which will be utilized for executing Deployment Scripts in Bicep.
- A Service Principal with Contributor rights at the subscription level.
- Access to the source code for this solution, available at:
Solution Overview
This reference architecture illustrates a serverless web application. We will craft a Bicep template that provisions the following resources:
- Azure API Management
- Azure CDN
- Azure Cosmos DB for MongoDB
- Azure Functions (Windows)
- Azure Key Vault (Bring Your Own)
- Azure Storage Account for hosting the static website
The solution will encompass these files:
- 📄 main.bicep: The primary Bicep template
- 📄 azuredeploy.parameters.json: This parameter file contains the values needed for deploying your Bicep template.
- 📁 modules: This directory will house Bicep modules essential for deploying the solution.
Next, we will dissect the main.bicep file. You can explore additional Bicep modules in the GitHub repository.
Section 1.1: Azure Bicep Template — Defining Parameters
Create a new file in your working directory and title it main.bicep. We will set up the following parameters:
@description('Suffix for naming resources')
param appNameSuffix string = 'app${uniqueString('azinsider')}'
@allowed([
'dev'
'test'
'prod'
])
@description('Environment')
param environmentType string = 'dev'
@description('Do you want to create new APIM?')
param createApim bool = true
@description('APIM name')
param apimName string = 'apim-${appNameSuffix}-${environmentType}'
@description('APIM resource group')
param apimResourceGroup string = resourceGroup().name
@description('Do you want to create new vault?')
param createKeyVault bool = true
@description('Key Vault name')
param keyVaultName string = 'kv-${appNameSuffix}-${environmentType}'
@description('Key Vault resource group')
param keyVaultResourceGroup string = resourceGroup().name
@description('User assigned managed identity name')
param userAssignedIdentityName string = 'configDeployer'
@description('User assigned managed identity resource group')
param userAssignedIdentityResourceGroup string = 'managedIdentity'
@description('API friendly name')
param apimApiName string = 'azinsider-api'
param resourceTags object = {
ProjectType: 'Azure Serverless Web'
Purpose: 'AzInsider-Demo'
}
param location string = resourceGroup().location
Section 1.2: Azure Bicep Template — Defining Variables
Here, we will establish the following variables:
var staticWebsiteStorageAccountName = '${appNameSuffix}${environmentType}'
var cdnProfileName = 'cdn-${appNameSuffix}-${environmentType}'
var functionStorageAccountName = 'fn${appNameSuffix}${environmentType}'
var functionAppName = 'fn-${appNameSuffix}-${environmentType}'
var functionRuntime = 'dotnet'
var appServicePlanName = 'asp-${appNameSuffix}-${environmentType}'
var appInsightsName = 'ai-${appNameSuffix}-${environmentType}'
var cosmosDbName = '${appNameSuffix}-${environmentType}'
var cosmosDbAccountName = 'cosmos-${appNameSuffix}-${environmentType}'
// SKUs
var functionSku = environmentType == 'prod' ? 'EP1' : 'Y1'
var apimSku = environmentType == 'prod' ? 'Standard' : 'Developer'
// static values
var cosmosDbCollectionName = 'items'
Section 1.3: Azure Bicep Template — Declaring Resources
We will define the following resources:
resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' existing = {
name: userAssignedIdentityName
scope: resourceGroup(userAssignedIdentityResourceGroup)
}
resource appInsights 'Microsoft.Insights/components@2018-05-01-preview' = {
name: appInsightsName
location: location
kind: 'web'
properties: {
Application_Type: 'web'
publicNetworkAccessForIngestion: 'Enabled'
publicNetworkAccessForQuery: 'Enabled'
}
}
// Additional modules follow...
Chapter 2: Deployment of Azure Bicep Template
To deploy the Bicep template, utilize the command below:
You can verify the deployment results in the Azure Portal.
👉 Join the AzInsider email list here.
-Dave R.