0Pricing
Cloud & IT Cert Prep · Lesson

Bicep: Modern Azure IaC

Learn Bicep's concise syntax as a strongly-typed abstraction over ARM JSON, convert an existing ARM template to Bicep, and deploy it with the Azure CLI.

Bicep: Modern Azure IaC is a free Cloud & IT Cert Prep lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Cloud & IT Cert Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is Bicep and Why Use It?

Bicep is a domain-specific language (DSL) developed by Microsoft as a strongly-typed, concise alternative to ARM JSON templates. Bicep compiles down to standard ARM JSON, so it uses the same ARM deployment engine and supports all Azure resource types on day one. Bicep removes much of the boilerplate required by raw JSON and provides better type safety and IntelliSense support.

Bicep vs ARM JSON Syntax Comparison

The same storage account that requires ~25 lines of JSON in an ARM template needs only ~8 lines in Bicep. Bicep eliminates '$schema', contentVersion, the resources array wrapper, and the verbose expression syntax. Property names and types remain identical since Bicep is a direct abstraction layer over ARM JSON — there is zero runtime difference.

// Bicep: deploy a storage account
param storageAccountName string
param location string = resourceGroup().location
param sku string = 'Standard_LRS'

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: sku
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
    minimumTlsVersion: 'TLS1_2'
  }
}

Parameters and Decorators in Bicep

Bicep parameters use a concise param name type = defaultValue syntax. You can apply decorators (prefixed with @) directly above a parameter to add constraints such as @minLength(), @maxLength(), @allowed(), and @description(). The @secure() decorator marks a parameter as sensitive, equivalent to secureString in ARM JSON.

@description('Globally unique name for the storage account')
@minLength(3)
@maxLength(24)
param storageAccountName string

@allowed(['Standard_LRS', 'Standard_GRS', 'Premium_LRS'])
param sku string = 'Standard_LRS'

@secure()
param adminPassword string

Variables and Expressions in Bicep

Bicep variables are declared with the var keyword and can contain any expression, including string interpolation using '${value}' syntax. String interpolation is one of the most readable improvements over ARM JSON — no more concat() function calls. Bicep also supports conditional expressions using the ternary operator condition ? trueValue : falseValue.

param environment string = 'dev'
param baseName string = 'myapp'

var uniqueSuffix = uniqueString(resourceGroup().id)
var storageAccountName = '${baseName}${environment}${uniqueSuffix}'
var isProd = environment == 'prod'
var skuName = isProd ? 'Standard_GRS' : 'Standard_LRS'

Resource Declarations and Symbolic Names

In Bicep, each resource gets a symbolic name — an identifier used to reference it within the template. The symbolic name is not the same as the resource's Azure name. Use symbolic names to access resource properties and establish implicit dependencies by referencing one resource inside another, eliminating the need for an explicit dependsOn array.

resource vnet 'Microsoft.Network/virtualNetworks@2023-05-01' = {
  name: 'myVNet'
  location: location
  properties: {
    addressSpace: { addressPrefixes: ['10.0.0.0/16'] }
  }
}

// Implicit dependency via symbolic name reference
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-05-01' = {
  parent: vnet  // Bicep knows to create vnet first
  name: 'mySubnet'
  properties: {
    addressPrefix: '10.0.1.0/24'
  }
}

Outputs in Bicep

Bicep outputs are declared with the output keyword followed by the output name, type, and value. You can reference a deployed resource's properties using the symbolic name and dot notation, which is far more readable than ARM's reference() function. Outputs are essential for passing values between Bicep module calls.

output storageAccountName string = storageAccount.name
output blobEndpoint string = storageAccount.properties.primaryEndpoints.blob
output storageAccountId string = storageAccount.id

Bicep Modules

Bicep modules are the equivalent of linked templates in ARM JSON, allowing you to break infrastructure into reusable components. A module is simply another .bicep file. You reference it using the module keyword, pass parameters, and consume its outputs. Modules can also be published to and consumed from an Azure Container Registry for team-wide reuse.

// main.bicep — consuming a storage module
module storage './modules/storage.bicep' = {
  name: 'storageDeploy'
  params: {
    storageAccountName: 'myuniquestorage'
    location: location
    sku: 'Standard_LRS'
  }
}

// Reference module output in parent template
output blobUri string = storage.outputs.blobEndpoint

Converting ARM Templates to Bicep

If you already have existing ARM JSON templates, the Bicep CLI can decompile them to Bicep using bicep decompile. The result may need some manual cleanup, but it gives you an excellent starting point. Microsoft also provides an online playground at aka.ms/bicepdemo where you can paste ARM JSON and see the equivalent Bicep in real time.

# Install the Bicep CLI (or use it via Azure CLI)
az bicep install
az bicep upgrade

# Decompile existing ARM JSON to Bicep
az bicep decompile --file azuredeploy.json
# Produces azuredeploy.bicep in the same directory

# Compile Bicep to ARM JSON (for inspection)
az bicep build --file main.bicep

Deploying Bicep with Azure CLI

The Azure CLI supports Bicep files directly — you do not need to manually compile to ARM JSON before deploying. Pass the .bicep file path to az deployment group create with the --template-file flag, and the CLI compiles it transparently. The same validate and what-if subcommands work with Bicep files exactly as with ARM JSON.

# Deploy a Bicep file directly
az deployment group create \
  --resource-group MyRG \
  --template-file main.bicep \
  --parameters storageAccountName=myprodstore environment=prod

# What-if preview with Bicep
az deployment group what-if \
  --resource-group MyRG \
  --template-file main.bicep \
  --parameters storageAccountName=myprodstore environment=prod

Loops and Conditions in Bicep

Bicep supports resource loops using the for ... in syntax to create multiple instances of a resource from an array parameter, eliminating copy-paste duplication. The if keyword enables conditional resource deployment — include a resource only when a certain condition is true. Both features are compiled into ARM's copy and condition constructs respectively.

// Loop: create multiple storage accounts
param storageNames array = ['alpha', 'beta', 'gamma']

resource stores 'Microsoft.Storage/storageAccounts@2023-01-01' = [for name in storageNames: {
  name: '${name}${uniqueString(resourceGroup().id)}'
  location: location
  sku: { name: 'Standard_LRS' }
  kind: 'StorageV2'
}]

// Condition: only deploy in prod
param deployKeyVault bool = false

resource kv 'Microsoft.KeyVault/vaults@2023-07-01' = if (deployKeyVault) {
  name: 'myKeyVault'
  location: location
  properties: { sku: { family: 'A', name: 'standard' }, tenantId: subscription().tenantId, accessPolicies: [] }
}

Bicep Tooling and Linting

The Bicep extension for Visual Studio Code provides rich IntelliSense, type checking, and inline error highlighting as you type. The Bicep CLI includes a linter that checks for best-practice violations such as unused parameters, missing descriptions, and incorrect API versions. Run az bicep lint --file main.bicep in your CI pipeline to catch issues before deployment.

# Run the Bicep linter
az bicep lint --file main.bicep

# Format a Bicep file
az bicep format --file main.bicep

# Generate resource type documentation
az bicep generate-params --file main.bicep --output-format json

Quick Check

Test your understanding of Microsoft Azure Fundamentals (AZ-900) concepts from this lesson.

Lesson Recap

In this lesson you learned: Bicep is a concise, strongly-typed abstraction over ARM JSON that compiles to standard ARM templates, modules and loops enable reusable and DRY infrastructure code, and the Azure CLI deploys Bicep files directly supporting the same validate/what-if/deploy workflow. Next up we explore Terraform on Azure.

Frequently asked questions

Is the “Bicep: Modern Azure IaC” lesson free?

Yes — the full text of “Bicep: Modern Azure IaC” is free to read here on the web, and the Cloud & IT Cert Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Cloud & IT Cert Prep course, upgrade to CoddyKit PRO.

What will I learn in “Bicep: Modern Azure IaC”?

Learn Bicep's concise syntax as a strongly-typed abstraction over ARM JSON, convert an existing ARM template to Bicep, and deploy it with the Azure CLI. You practise Cloud & IT Cert Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Cloud & IT Cert Prep?

No prior experience is required. Cloud & IT Cert Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Bicep: Modern Azure IaC” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Cloud & IT Cert Prep lesson?

Yes. Every Cloud & IT Cert Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. How Azure Resource Manager Works
  2. Writing ARM Templates
  3. Bicep: Modern Azure IaC
  4. Terraform on Azure
← Back to Cloud & IT Cert Prep