Discovering Azure Bicep
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.
- Open Azure Cloud Shell.
- Create a file named
main.bicep. - 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
- Create a resource group:
az group create -n az104-bicep-rg -l eastus
- Deploy the file:
az deployment group create \
-g az104-bicep-rg \
-f main.bicep \
-p storageName=az104bicep$RANDOM
- Review the output.
- Open the resource group deployment history.
- Delete the resource group after the lab.
