Bicep
English
Bicep is a domain-specific language (DSL) for deploying Azure resources declaratively.
It simplifies the process of defining and deploying infrastructure by providing a more concise syntax compared to traditional JSON-based ARM templates.
Bicep files use the .bicep file extension and can be compiled into ARM templates for deployment.
Key Features of Bicep
- Declarative syntax: Describe the resources and properties you want Azure to deploy.
- Concise, typed authoring: Bicep is more concise than equivalent ARM JSON and provides type checking and editor diagnostics.
- Modules: Split deployments into reusable files, pass parameters, and consume outputs.
- Parameters, variables, and outputs: Separate deployment inputs from resource definitions and return useful values.
- Loops, conditions, and functions: Express repeated or conditional resources and compute values in the template.
- Dependency handling: Bicep infers dependencies when one resource references another; explicit dependencies are available when needed.
- Azure integration: Bicep compiles to an ARM template, and Azure Resource Manager performs the deployment. There is no separate Bicep state file to maintain.
- Tooling: The Bicep Visual Studio Code extension provides syntax validation, IntelliSense, and formatting support.
- Resource provider registration: During deployment, Azure Resource Manager can register providers declared in the template. This requires registration permission, and supporting providers not declared in the template might need to be registered separately.
Bicep templates vs Bicep modules (what they are)
In Bicep you will usually work with templates and modules.
Bicep template (the main deployment file)
A template is a .bicep file that represents a complete deployment at a certain scope (resource group / subscription / etc.).
You can think of it as the main plan:
- Defines the parameters you need (name, location, SKU, etc.)
- Defines the resources Azure must create/update
- Often calls modules for reusable building blocks
Common names: main.bicep, deploy.bicep, rg.bicep.
Bicep module (a reusable building block)
A module is also a .bicep file, but it is designed to be called from another Bicep file.
You can think of it as a LEGO sub-build:
- One module does one job (e.g., "create a VNet", "create a storage account", "create diagnostics settings")
- You can reuse the same module in many projects/environments
- You pass input values to the module using parameters
- A module can return useful values using outputs (for example the resource ID)
Why use modules:
- Reuse: don’t copy/paste the same resources everywhere
- Consistency: security/naming/tags are applied the same way
- Easier maintenance: fix a bug once in the module, then redeploy
- Cleaner main files: the main template stays readable
How modules work (simple example)
Example folder structure
infra/
main.bicep
templates/
vnet.bicep
storage.bicep
Module file (example): templates/vnet.bicep
// Creates a VNet and outputs its resource ID
param location string
param vnetName string
param addressPrefix string
resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: [
addressPrefix
]
}
}
}
output vnetId string = vnet.id
Main template file (example): main.bicep
param location string = resourceGroup().location
param environment string
param baseName string
var vnetName = '${baseName}-${environment}-vnet'
module vnetModule './templates/vnet.bicep' = {
name: 'deployVnet'
params: {
location: location
vnetName: vnetName
addressPrefix: '10.10.0.0/16'
}
}
// You can use module outputs in the main template:
output deployedVnetId string = vnetModule.outputs.vnetId
Quick summary
- Template: the main
.bicepfile you deploy. - Module: a reusable
.bicepbuilding block called by the template. - Parameters: inputs (values you provide).
- Outputs: results (values you can use later).
What a Bicep deploy file does
A Bicep file (.bicep) is an Infrastructure as Code (IaC) template for Azure.
Think of it as a recipe that describes what Azure should create or change.
What it contains
A typical Bicep file defines:
- Scope: Where you deploy (resource group, subscription, management group, tenant)
Example: creating a resource group requirestargetScope = 'subscription'. - Parameters (
param): Values you can change without editing the template (like location, names, SKU). - Resources (
resource): The actual Azure things to deploy (resource groups, VNets, storage accounts, etc.). - (Optional) Outputs: Values you want to print after deployment (like resource IDs).
What happens when you deploy it
When you run a command like:
az deployment sub create --template-file .\resourcegroup-networking.bicep --location westeurope
The Azure CLI compiles the Bicep file to an ARM JSON template, then submits the deployment to Azure Resource Manager. Resource Manager will:
- Validate the deployment and its resource definitions.
- Create or update resources declared in the template. The default deployment mode is incremental: resources omitted from the template are left in place.
For a resource that already exists, Resource Manager reapplies the properties in the template. Properties you omit can be reset to their default values, so include all non-default settings you want to retain. Use the what-if operation before deployment when you want to preview proposed changes.
A Bicep file describes the intended configuration; it does not automatically detect or correct every difference between that description and the live environment.
Why use parameters?
If your .bicep file hardcodes values like:
- resource group name =
rg-networking-corp-pro-001 - location =
westeurope
targetScope = 'subscription'
param location string = 'westeurope'
param name string = 'rg-networking-corp-pro-001'
resource resResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' = {
location: location
name: name
}
Then deploying the same template for another environment (like test, acceptance, production) becomes annoying because you must edit the template each time.
That creates risks:
- Someone forgets to change a value and deploys to the wrong place
- You end up with multiple slightly different templates (template drift)
- It’s harder to review and standardize
Parameters solve part of this, because you can pass different values in each deployment.
What a .bicepparam file is (and why you use it)
A Bicep parameter file (.bicepparam) is a separate file that stores parameter values for a specific deployment.
Why it’s useful
It lets you keep:
- One shared template (
main.bicep) = the "recipe" - Multiple parameter files (
dev.bicepparam,test.bicepparam,prod.bicepparam) = the "ingredient lists"
This is the cleanest way to do multiple deployments because:
- You don’t modify the template per environment
- You can deploy the same template repeatedly with different settings
- It’s easier for juniors/operators: "pick the right param file and run the command"
- It’s better for change control and audits (you can review param changes separately)
Simple example(s)
Template
This stays the same for every environment:
targetScope = 'subscription'
param location string
param name string
resource resResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' = {
name: name
location: location
}
Parameter file for Development
using './resourcegroup-networking.bicep'
param location = 'westeurope'
param name = 'rg-networking-dev-001'
Parameter file for Production
using './resourcegroup-networking.bicep'
param location = 'westeurope'
param name = 'rg-networking-prd-001'
Deploy Development vs Production
You deploy the same template, just swap the parameter file:
For .bicepparam deployment with Azure CLI, use Azure CLI 2.53.0 or later and Bicep CLI 0.22.x or later.
az deployment sub create --location westeurope --parameters .\dev.bicepparam
az deployment sub create --location westeurope --parameters .\prod.bicepparam
Overview
.bicep= blueprint / recipe (what should be built).bicepparam= configuration sheet (names, regions, sizes for this environment)- Deployment command = "build it now" using the blueprint + configuration
Nederlands
Bicep is een domeinspecifieke taal (DSL) voor het declaratief implementeren van Azure-resources. De taal maakt het definiëren en implementeren van infrastructuur eenvoudiger met een beknoptere syntaxis dan traditionele ARM-templates in JSON. Bicep-bestanden hebben de extensie .bicep en kunnen voor implementatie worden gecompileerd naar ARM-templates.
Belangrijke functies van Bicep
- Declaratieve syntaxis: Beschrijf welke resources en eigenschappen Azure moet implementeren.
- Beknopte, getypeerde code: Bicep is beknopter dan equivalente ARM-JSON en biedt typecontroles en diagnostiek in de editor.
- Modules: Verdeel implementaties over herbruikbare bestanden, geef parameters door en gebruik uitvoerwaarden.
- Parameters, variabelen en uitvoerwaarden: Scheid invoer voor een implementatie van de resource definities en geef nuttige waarden terug.
- Lussen, voorwaarden en functies: Beschrijf herhaalde of voorwaardelijke resources en bereken waarden in de template.
- Afhankelijkheden: Bicep leidt afhankelijkheden af wanneer een resource naar een andere resource verwijst. Zo nodig kun je afhankelijkheden ook expliciet opgeven.
- Integratie met Azure: Bicep wordt gecompileerd naar een ARM-template en Azure Resource Manager voert de implementatie uit. Je hoeft geen afzonderlijk Bicep-statusbestand te beheren.
- Hulpmiddelen: De Bicep-extensie voor Visual Studio Code biedt syntaxisvalidatie, IntelliSense en ondersteuning voor opmaak.
- Registratie van resource providers: Tijdens een implementatie kan Azure Resource Manager de providers registreren die in de template zijn gedeclareerd. Hiervoor zijn registratierechten nodig. Ondersteunende providers die niet in de template staan, moeten soms afzonderlijk worden geregistreerd.
Bicep-templates en Bicep-modules
In Bicep werk je doorgaans met templates en modules.
Bicep-template (het hoofdimplementatiebestand)
Een template is een .bicep-bestand dat een volledige implementatie op een bepaalde scope beschrijft (resourcegroep, abonnement, enzovoort).
Je kunt dit zien als het hoofdplan:
- Definieert de benodigde parameters (naam, locatie, SKU, enzovoort).
- Definieert de resources die Azure moet maken of bijwerken.
- Roept vaak modules aan voor herbruikbare bouwstenen.
Veelgebruikte bestandsnamen zijn main.bicep, deploy.bicep en rg.bicep.
Bicep-module (een herbruikbare bouwsteen)
Een module is ook een .bicep-bestand, maar is bedoeld om vanuit een ander Bicep-bestand te worden aangeroepen.
Je kunt dit zien als een deel van een bouwwerk:
- Een module doet één ding (bijvoorbeeld een VNet, een storage account of diagnostische instellingen maken).
- Je kunt dezelfde module in meerdere projecten en omgevingen hergebruiken.
- Je geeft invoerwaarden door aan de module met parameters.
- Een module kan nuttige waarden teruggeven met uitvoerwaarden, bijvoorbeeld de resource-ID.
Waarom modules gebruiken:
- Hergebruik: voorkom dat je dezelfde resources steeds opnieuw kopieert.
- Consistentie: pas beveiliging, naamgeving en tags op dezelfde manier toe.
- Eenvoudiger onderhoud: los een fout op in de module en implementeer deze opnieuw.
- Overzichtelijkere main templates: de main template blijft leesbaar.
Zo werken modules (eenvoudig voorbeeld)
Voorbeeld van een mappenstructuur
infra/
main.bicep
modules/
vnet.bicep
storage.bicep
Modulebestand: modules/vnet.bicep
// Maakt een VNet en geeft de resource-ID terug
param location string
param vnetName string
param addressPrefix string
resource vnet 'Microsoft.Network/virtualNetworks@2023-11-01' = {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: [
addressPrefix
]
}
}
}
output vnetId string = vnet.id
Main bestand: main.bicep
param location string = resourceGroup().location
param environment string
param baseName string
var vnetName = '${baseName}-${environment}-vnet'
module vnetModule './modules/vnet.bicep' = {
name: 'deployVnet'
params: {
location: location
vnetName: vnetName
addressPrefix: '10.10.0.0/16'
}
}
// Gebruik module-uitvoerwaarden in de main template:
output deployedVnetId string = vnetModule.outputs.vnetId
Korte samenvatting
- Template: het hoofd-Bicep-bestand dat je implementeert.
- Module: een herbruikbare Bicep-bouwsteen die vanuit een template wordt aangeroepen.
- Parameters: invoerwaarden.
- Uitvoerwaarden: resultaten die je kunt gebruiken.
Wat doet een Bicep-implementatiebestand?
Een Bicep-bestand (.bicep) is een Infrastructure as Code-template (IaC) voor Azure. Je kunt het zien als een recept dat beschrijft welke resources Azure moet maken of wijzigen.
Wat staat erin?
Een typisch Bicep-bestand definieert:
- Scope: waar je implementeert (resourcegroep, abonnement, beheergroep of tenant). Voorbeeld: voor het maken van een resourcegroep is
targetScope = 'subscription'nodig. - Parameters (
param): waarden die je kunt aanpassen zonder de template te wijzigen, zoals locatie, namen en SKU. - Resources (
resource): de Azure-resources zelf, zoals resourcegroepen, VNets en storage accounts. - Uitvoerwaarden (
output, optioneel): waarden die je na de implementatie wilt tonen, zoals resource-ID's.
Wat gebeurt er tijdens een implementatie?
Bijvoorbeeld, met deze opdracht:
az deployment sub create --template-file .\resourcegroup-networking.bicep --location westeurope
De Azure CLI compileert het Bicep-bestand naar een ARM-template in JSON en stuurt de implementatie naar Azure Resource Manager. Resource Manager voert vervolgens de volgende stappen uit:
- Valideert de implementatie en de resourcedefinities.
- Maakt resources die in de template staan of werkt ze bij. De standaardimplementatiemodus is incrementeel: resources die niet in de template staan, blijven bestaan.
Voor een bestaande resource past Resource Manager de eigenschappen uit de template opnieuw toe. Eigenschappen die je weglaat, kunnen worden teruggezet naar hun standaardwaarde. Neem daarom alle niet-standaardinstellingen op die je wilt behouden. Gebruik de bewerking what-if vóór de implementatie om de voorgestelde wijzigingen te bekijken.
Een Bicep-bestand beschrijft de gewenste configuratie. Het detecteert of herstelt niet automatisch elk verschil tussen die beschrijving en de daadwerkelijke omgeving.
Waarom parameters gebruiken?
Als je .bicep-bestand waarden vastlegt, zoals:
- naam van de resourcegroep =
rg-networking-corp-pro-001 - locatie =
westeurope
targetScope = 'subscription'
param location string = 'westeurope'
param name string = 'rg-networking-corp-pro-001'
resource resResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' = {
location: location
name: name
}
Dan is het lastig om dezelfde template voor een andere omgeving te gebruiken, zoals test, acceptatie of productie: je moet het bestand telkens aanpassen.
Dat brengt risico's met zich mee:
- Iemand vergeet een waarde te wijzigen en implementeert per ongeluk naar de verkeerde omgeving.
- Er ontstaan meerdere templates die net van elkaar verschillen.
- Beoordelen en standaardiseren wordt lastiger.
Met parameters kun je per implementatie andere waarden opgeven zonder de template aan te passen.
Wat is een .bicepparam-bestand en waarom gebruik je het?
Een Bicep-parameterbestand (.bicepparam) is een apart bestand met parameterwaarden voor een specifieke implementatie.
Waarom is dat handig?
Je kunt het volgende gescheiden houden:
- Eén gedeelde template (
main.bicep): het recept. - Meerdere parameterbestanden (
dev.bicepparam,test.bicepparam,prod.bicepparam): de waarden voor elke omgeving.
Dit is handig voor implementaties in meerdere omgevingen, omdat:
- Je de template niet per omgeving hoeft aan te passen.
- Je dezelfde template met verschillende instellingen kunt implementeren.
- Beheerders eenvoudig het juiste parameterbestand kunnen kiezen.
- Wijzigingen in parameters afzonderlijk kunnen worden beoordeeld.
Eenvoudig voorbeeld
Bicep-template
Deze blijft hetzelfde voor elke omgeving:
targetScope = 'subscription'
param location string
param name string
resource resResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' = {
name: name
location: location
}
Parameterbestand voor ontwikkeling
using './resourcegroup-networking.bicep'
param location = 'westeurope'
param name = 'rg-networking-dev-001'
Parameterbestand voor productie
using './resourcegroup-networking.bicep'
param location = 'westeurope'
param name = 'rg-networking-prd-001'
Ontwikkeling of productie implementeren
Je gebruikt dezelfde template en wisselt alleen het parameterbestand.
Voor implementatie van .bicepparam-bestanden met Azure CLI heb je Azure CLI 2.53.0 of hoger en Bicep CLI 0.22.x of hoger nodig.
az deployment sub create --location westeurope --parameters .\dev.bicepparam
az deployment sub create --location westeurope --parameters .\prod.bicepparam
Overzicht
.bicep= blauwdruk/recept: wat er moet worden gebouwd..bicepparam= configuratiebestand: namen, regio's en groottes voor deze omgeving.- Implementatieopdracht = uitvoeren: de blauwdruk en configuratie gebruiken om de implementatie te starten.