What is Azure Bicep?
Bicep is a Domain Specific Language (DSL) for Azure Resource Manager. It simplifies ARM JSON templates into readable and modular code for Infrastructure as Code on Azure.
Basic Structure
@description('Storage account name')
param storageAccountName string
param storageSku string = 'Standard_LRS'
var location = resourceGroup().location
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
sku: {
name: storageSku
}
kind: 'StorageV2'
}
output storageEndpoint string = storageAccount.properties.primaryEndpoints.blob
Parameters
@description('Admin username')
param adminUser string = 'azureuser'
@secure()
param adminPassword string
@allowed(['Standard_LRS', 'Standard_GRS'])
param sku string
Variables
var prefix = 'demo'
var uniqueName = '${prefix}${uniqueString(resourceGroup().id)}'
var subnetNames = ['web', 'app', 'db']
Expressions & Interpolation
var fullName = '${prefix}-${environment}-${location}'
var uniqueName = toLower(uniqueString(resourceGroup().id, 'key'))
Resource Declaration
resource myVnet 'Microsoft.Network/virtualNetworks@2023-01-01' = {
name: 'vnet-${uniqueString(resourceGroup().id)}'
location: location
properties: {
addressSpace: {
addressPrefixes: ['10.0.0.0/16']
}
}
}
Resource Dependencies
Implicit dependency:
resource nic 'Microsoft.Network/networkInterfaces@2023-01-01' = {
name: 'vmNic'
properties: {
ipConfigurations: [
{
name: 'ipconfig'
properties: {
subnet: { id: subnet.id }
}
}
]
}
}
Explicit dependency:
dependsOn: [ nic, storageAccount ]
Loops
var subnets = [
{ name: 'web', prefix: '10.0.1.0/24' }
{ name: 'app', prefix: '10.0.2.0/24' }
]
resource vnet 'Microsoft.Network/virtualNetworks@2023-01-01' = {
name: 'myVnet'
properties: {
addressSpace: { addressPrefixes: ['10.0.0.0/16'] }
subnets: [for subnet in subnets: {
name: subnet.name
properties: { addressPrefix: subnet.prefix }
}]
}
}
Conditional Deployment
param enableDiagnostics bool = true
resource diag 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (enableDiagnostics) {
name: 'diagSetting'
properties: {
...
}
}
Modules
Main file:
module storage './storage.bicep' = {
name: 'storageModule'
params: {
storageAccountName: 'mystorage'
location: location
}
}
storage.bicep:
param storageAccountName string
param location string
resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
sku: { name: 'Standard_LRS' }
kind: 'StorageV2'
}
output storageId string = storage.id
Outputs
output storageId string = storage.id
output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storage.name}'
Common Functions
resourceGroup()– Current resource groupuniqueString()– Deterministic unique IDconcat()– Join stringslength()– Array or string lengthcontains()– Checks if array contains valueif()– Inline conditionjson()– Parse JSON
Azure CLI Commands
az deployment group create \
--resource-group myRG \
--template-file main.bicep \
--parameters storageSku=Standard_LRS
az deployment group validate \
--resource-group myRG \
--template-file main.bicep
az deployment group what-if \
--resource-group myRG \
--template-file main.bicep
Scopes
targetScope = 'subscription'
resource rg 'Microsoft.Resources/resourceGroups@2023-01-01' = {
name: 'myResourceGroup'
location: 'eastus'
}
Best Practices
- Use modules for reusable components
- Validate parameters using
@allowed,@minLength - Tag all resources consistently
- Use loops instead of duplicate code
- Preview changes using
what-if - Avoid exposing secrets in outputs
- Keep Bicep files under version control
Helpful CLI Commands
az bicep install
az bicep upgrade
az bicep build --file main.bicep
az bicep decompile --file template.json
Common Resource Types
- Storage Account –
Microsoft.Storage/storageAccounts@2023-01-01 - Virtual Network –
Microsoft.Network/virtualNetworks@2023-01-01 - Virtual Machine –
Microsoft.Compute/virtualMachines@2023-01-01 - App Service –
Microsoft.Web/sites@2023-01-01 - Key Vault –
Microsoft.KeyVault/vaults@2023-01-01