Azure Bicep is the next-generation language for Azure infrastructure as code, replacing ARM templates. With cleaner syntax, modules, and first-class tooling, Bicep significantly improves the IaC developer experience. This guide covers Bicep fundamentals, module patterns, deployment strategies, and migration from ARM templates.
Bicep vs ARM Templates
| Feature | ARM JSON | Bicep |
|---|---|---|
| Syntax | Verbose JSON | Clean DSL |
| Line Count | 100% | ~50% |
| Modules | Linked templates | Native modules |
| IntelliSense | Limited | Full VS Code support |
| Compilation | Same | Compiles to ARM |
Basic Syntax
// Parameters with decorators
@description('The environment type')
@allowed(['dev', 'staging', 'prod'])
param environment string = 'dev'
@secure()
param adminPassword string
// Variables
var storageAccountName = 'st${uniqueString(resourceGroup().id)}'
var isProduction = environment == 'prod'
// Resources
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: storageAccountName
location: resourceGroup().location
sku: {
name: isProduction ? 'Standard_GRS' : 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
supportsHttpsTrafficOnly: true
}
}
// Outputs
output storageEndpoint string = storageAccount.properties.primaryEndpoints.blob
Module Pattern
// modules/storage.bicep
param name string
param location string
param sku string = 'Standard_LRS'
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: name
location: location
sku: { name: sku }
kind: 'StorageV2'
}
output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}'
// main.bicep
module storage 'modules/storage.bicep' = {
name: 'storageDeployment'
params: {
name: 'stmyapp${environment}'
location: resourceGroup().location
sku: environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS'
}
}
// Reference module output
output storageConnection string = storage.outputs.connectionString
Deployment with What-If
# Preview changes (what-if)
az deployment group what-if \
--resource-group my-rg \
--template-file main.bicep \
--parameters environment=prod
# Deploy
az deployment group create \
--resource-group my-rg \
--template-file main.bicep \
--parameters environment=prod
Registry for Shared Modules
# Publish module to registry
az bicep publish \
--file modules/storage.bicep \
--target br:myregistry.azurecr.io/bicep/storage:v1.0
// Consume from registry
module storage 'br:myregistry.azurecr.io/bicep/storage:v1.0' = {
name: 'storageDeployment'
params: {
name: 'stmyapp'
location: resourceGroup().location
}
}
Key Takeaways
- Bicep compiles to ARM—same deployment engine
- 50% less code than ARM JSON
- Modules enable reusable infrastructure patterns
- What-if preview prevents surprise changes
- Private registry for enterprise module sharing
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.