Discovering Azure Bicep

IntermediateTopic20 min5 min readAzure

AZ-104 notes: Discovering Azure Bicep. Covers key concepts for the Azure Administrator Associate exam.

  • Structured Summary + Deep Technical Understanding

Primary services involved:

  • Azure Bicep
  • Azure Resource Manager
  • Azure Cloud Shell

Official Documentation:

Bicep overview:

Bicep syntax reference:

Deploy Bicep with PowerShell:

Deploy Bicep with CLI:

1️⃣ What Is Azure Bicep?

Azure Bicep is:

  • ✔ A domain-specific language (DSL) for deploying Azure resources ✔ A cleaner alternative to ARM JSON templates ✔ An abstraction layer over ARM templates ✔ Infrastructure as Code (IaC)
  • It simplifies writing Azure deployments.

2️⃣ Why Bicep Was Created

Problem with ARM templates:

  • JSON is verbose
  • Difficult to read
  • Hard to maintain at scale
  • Nested brackets and quotes become messy

Example reality:

  • ARM JSON = machine-friendly Bicep = human-friendly

Bicep dramatically reduces:

  • Boilerplate
  • Syntax clutter
  • Complexity

3️⃣ Bicep vs ARM – Architecture Flow

ARM Workflow

  • Write ARM template (JSON)
  • Deploy template
  • ARM processes request
  • Resource Providers deploy resources

Bicep Workflow

  • Write Bicep file
  • Bicep compiles to ARM template
  • ARM processes template
  • Resource Providers deploy resources

Important:

  • 🚨 Bicep does NOT replace ARM 🚨 Bicep compiles into ARM JSON 🚨 ARM is still the engine

4️⃣ Bicep File Structure (From Demo)

The sample Bicep file included:

  • param location string = resourceGroup().location
  • param webAppName string
  • resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  • ...
  • }
  • resource webApp 'Microsoft.Web/sites@2022-03-01' = {
  • ...
  • }

Key components observed:

  • ✔ Parameters ✔ Variables ✔ Resources ✔ Symbolic names ✔ Built-in functions

5️⃣ Understanding Key Bicep Concepts

🔹 Parameters

  • Used to pass values at deployment time.

Example:

  • param location string = resourceGroup().location

Meaning:

  • Type = string
  • Default = resource group location
  • Uses built-in ARM function

If no default is provided:

  • Deployment will prompt user.

🔹 Built-in Functions

Example used:

  • resourceGroup().location

This retrieves:

  • ✔ The location of the resource group ✔ Makes template portable across regions

Docs:

🔹 Symbolic Names (Very Important)

Example:

  • resource appServicePlan ...
  • appServicePlan is NOT the deployed name.

It is:

  • ✔ A symbolic reference inside the template ✔ Used for linking resources

Example reference:

  • serverFarmId: appServicePlan.id

This means:

  • Take the ID of that resource after deployment and assign it here.
  • This is how dependencies are managed cleanly in Bicep.

6️⃣ Quotation Rules Explained

In the demo:

  • name: webAppName
  • location: location

No quotes because:

  • ✔ They reference parameters/variables

But:

  • name: 'HardCodedName'
  • Uses quotes because it's a literal string.

7️⃣ Handling Global Uniqueness (Web App Name Error)

  • Web App names must be globally unique.

Initial issue:

Hardcoded:

  • name: 'AwesomeApp'

Error occurred:

  • Website with given name already exists.

Solution:

Create parameter:

  • param webAppName string
  • Now deployment prompts for unique name.

This makes template:

  • ✔ Reusable ✔ Environment-independent ✔ Production-ready

8️⃣ Deploying Bicep with PowerShell

Used in demo:

  • New-AzResourceGroupDeployment `
  • -ResourceGroupName $rg.ResourceGroupName `
  • -TemplateFile deploy.bicep

Deployment flow:

  • Bicep file → Compiled to ARM JSON → Sent to Azure Resource Manager → Resources deployed

9️⃣ Verifying Compilation

After deployment:

  • Resource Group → Deployments → Select deployment → Template

You see:

  • ARM JSON template

This confirms:

  • ✔ Bicep compiled into ARM ✔ ARM executed the deployment

🔟 Advantages of Azure Bicep

1️⃣1️⃣ Advanced Capabilities (Beyond Demo)

Bicep also supports:

  • ✔ Modules (reusable template blocks) ✔ Loops (for deploying multiple resources) ✔ Conditions (deploy only if true) ✔ Existing resource references ✔ Secure parameters

Example loop:

  • resource storageAccounts 'Microsoft.Storage/storageAccounts@2022-09-01' = [for i in range(0,3): {
  • name: 'storage${i}'
  • ...
  • }]

1️⃣2️⃣ Where Bicep Fits in DevOps

Typical workflow:

  • Git Repository → Bicep files → CI/CD pipeline → Bicep compiled → ARM deployment → Azure infrastructure

Common tools:

  • Azure DevOps
  • GitHub Actions
  • Azure CLI
  • PowerShell

1️⃣3️⃣ Exam-Relevant Points

✔ Bicep is GA (Generally Available) ✔ Bicep compiles to ARM JSON ✔ ARM remains underlying engine ✔ Symbolic names manage dependencies ✔ Parameters improve reusability ✔ Bicep supports same scopes as ARM (resource group, subscription, etc.)

1️⃣4️⃣ Bicep vs ARM Quick Comparison

1️⃣5️⃣ Mental Model

Think of Bicep as:

  • High-level language (like C#) ARM JSON as compiled IL Azure Resource Manager as runtime engine
  • You write Bicep → Azure runs ARM.

1️⃣6️⃣ Final Key Takeaways

  • ✔ Azure Bicep simplifies ARM template authoring ✔ It is NOT a replacement engine ✔ It compiles into ARM templates ✔ Symbolic names enable clean resource linking ✔ Parameters enable reusable deployments ✔ Default values improve portability ✔ All Azure deployments ultimately use ARM

If you'd like next:

  • 🧠 Bicep vs ARM deep comparison with side-by-side real examples
  • 🏗 Build a production multi-tier Bicep template step-by-step
  • 🔄 Convert ARM JSON to Bicep example
  • 🚀 CI/CD pipeline deploying Bicep
  • 📘 40 exam-style Bicep & ARM questions
  • Tell me what level you want to go next.

Hands-on: Deploy a Storage Account with Bicep

Goal: Write a small Bicep file and deploy it from Cloud Shell.

  1. Open Azure Cloud Shell.
  2. Create a file named main.bicep.
  3. Add this template:
param location string = resourceGroup().location
param storageName string

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

output blobEndpoint string = storage.properties.primaryEndpoints.blob
  1. Create a resource group:
az group create -n az104-bicep-rg -l eastus
  1. Deploy the file:
az deployment group create \
  -g az104-bicep-rg \
  -f main.bicep \
  -p storageName=az104bicep$RANDOM
  1. Review the output.
  2. Open the resource group deployment history.
  3. Delete the resource group after the lab.

More in Microsoft Azure