Infrastructure as Code mit Bicep: Der moderne Weg
Bicep ist die moderne Alternative zu ARM Templates. Lernen Sie, wie Sie Azure-Ressourcen deklarativ und type-safe definieren.
Bicep ist Microsofts neue Domain-Specific Language für Azure Resource Manager. Im Gegensatz zu JSON-basierten ARM Templates bietet Bicep eine deutlich bessere Developer Experience: weniger Boilerplate-Code, klare Syntax und native Tooling-Unterstützung direkt in VS Code. Wer einmal mit Bicep gearbeitet hat, möchte nie wieder rohe ARM-JSON-Dateien schreiben.
Warum Bicep?
- Type-Safety und IntelliSense – Der Bicep-Compiler erkennt Tippfehler und falsche Ressourcentypen bereits zur Entwicklungszeit, nicht erst beim Deployment.
- Kürzere und lesbarere Syntax – Vergleichbare ARM Templates sind oft 3–5× länger. Bicep spart durch Weglassen von Boilerplate-Konstrukten erheblich an Zeilen.
- Native Azure-Integration – Bicep wird direkt von Microsoft entwickelt und unterstützt neue Azure-Ressourcenversionen in der Regel am Tag der GA-Veröffentlichung.
- Module für Wiederverwendbarkeit – Gemeinsame Infrastrukturbausteine lassen sich als Module kapseln und aus öffentlichen oder privaten Registries referenzieren.
- Idempotente Deployments – Bicep-Dateien beschreiben den gewünschten Zustand; Azure Resource Manager sorgt dafür, dass die tatsächliche Infrastruktur diesem Zustand entspricht.
- Nahtlose ARM-Interoperabilität – Jede Bicep-Datei wird deterministisch in ein ARM-Template kompiliert. Es gibt keine versteckte Laufzeitlogik.
Beispiel: Storage Account
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
name: storageAccountName
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
}
Dieses Snippet definiert einen Storage Account mit lokal redundantem Speicher (Standard_LRS). Die Variablen storageAccountName und location werden als Parameter übergeben, sodass dieselbe Datei für mehrere Umgebungen wiederverwendet werden kann.
Parameter und Variablen
Sauber getrennte Parameter machen Bicep-Templates umgebungsunabhängig:
@description('Name des Storage Accounts (3–24 Zeichen, nur Kleinbuchstaben und Ziffern)')
@minLength(3)
@maxLength(24)
param storageAccountName string
@description('Azure-Region für alle Ressourcen')
param location string = resourceGroup().location
@allowed([
'Standard_LRS'
'Standard_GRS'
'Premium_LRS'
])
param skuName string = 'Standard_LRS'
Decoratoren wie @minLength, @maxLength und @allowed fügen Validierungsregeln direkt im Template hinzu – kein externes Schema nötig. Variablen (var) eignen sich für berechnete Werte, die intern verwendet werden, aber nicht von außen konfigurierbar sein müssen.
Module: Wiederverwendbare Bausteine
Das eigentliche Potenzial von Bicep liegt in seiner Modulstruktur. Komplexe Architekturen lassen sich in handliche, testbare Einheiten aufteilen:
// main.bicep
module storage './modules/storage.bicep' = {
name: 'storageDeployment'
params: {
storageAccountName: 'meinprojektstorage'
location: location
skuName: 'Standard_GRS'
}
}
module appService './modules/appService.bicep' = {
name: 'appServiceDeployment'
params: {
appName: 'mein-api-backend'
location: location
storageConnectionString: storage.outputs.connectionString
}
}
Module kommunizieren über outputs. Dadurch entsteht ein expliziter Abhängigkeitsgraph, den Azure Resource Manager automatisch auflöst – parallele Deployments inklusive.
Outputs und Abhängigkeiten
Outputs geben Werte aus einem Deployment zurück, etwa Connection Strings oder Ressource-IDs, die nachgelagerte Prozesse (CI/CD-Pipelines, andere Module) benötigen:
output storageAccountId string = storageAccount.id
output primaryEndpoint string = storageAccount.properties.primaryEndpoints.blob
output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=core.windows.net'
Hinweis: Sensitive Outputs wie Connection Strings sollten in der Produktion über Key Vault References bezogen werden, nicht direkt als Output.
Bicep in der CI/CD-Pipeline
Ein typischer GitHub Actions Workflow für Bicep-Deployments:
name: Deploy Infrastructure
on:
push:
branches: [main]
paths:
- 'infra/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Validate Bicep
run: az deployment group validate \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--template-file infra/main.bicep \
--parameters @infra/parameters.prod.json
- name: What-If Preview
run: az deployment group what-if \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--template-file infra/main.bicep \
--parameters @infra/parameters.prod.json
- name: Deploy
run: az deployment group create \
--resource-group ${{ vars.RESOURCE_GROUP }} \
--template-file infra/main.bicep \
--parameters @infra/parameters.prod.json
Der what-if-Schritt zeigt vor dem eigentlichen Deployment an, welche Ressourcen erstellt, geändert oder gelöscht werden – ein unverzichtbares Sicherheitsnetz, besonders bei Produktionsinfrastruktur.
Bicep vs. Terraform: Kurzer Vergleich
| Kriterium | Bicep | Terraform |
|---|---|---|
| Scope | Nur Azure | Multi-Cloud (AWS, GCP, Azure, …) |
| State Management | Kein lokaler State, Azure übernimmt | Lokale oder Remote State-Datei |
| Lernkurve | Gering (kennt man ARM, ist Bicep intuitiv) | Mittel (HCL, State-Konzept, Provider) |
| Azure-Aktualität | Tag-1-Support für neue APIs | Oft Verzögerung (Community-Provider) |
| Tooling | VS Code Extension, Azure CLI | Terraform CLI, viele IDEs |
| Modularisierung | Bicep Registry, öffentliche Module | Terraform Registry, sehr reif |
Für reine Azure-Umgebungen ist Bicep die schärfere Wahl. Wer Multi-Cloud oder ein bestehendes Terraform-Setup mitbringt, sollte abwägen.
Best Practices auf einen Blick
- Parameter-Dateien pro Umgebung –
parameters.dev.json,parameters.staging.json,parameters.prod.jsonhalten Konfigurationen sauber getrennt. - Naming Conventions mit Variablen – Ressourcennamen zentral aus Prefix + Umgebung + Region konstruieren, nie hartcodieren.
- Bicep Linter nutzen –
az bicep buildwarnt bei Best-Practice-Verstößen; in CI/CD als Pflicht-Schritt einbauen. - Key Vault für Secrets – Passwörter und Connection Strings nie als Klartext-Parameter übergeben, stattdessen
getSecret()aus Key Vault referenzieren. - Module versionieren – Module aus einer privaten Azure Container Registry mit expliziten Tags beziehen, nicht aus Branches.
what-ifvor jedem Prod-Deployment – Pflicht. Überraschungen in der Produktion sind teuer.
Fazit
Bicep ist kein Hype – es ist die logische Weiterentwicklung von ARM Templates für alle, die ernsthaft Infrastructure as Code auf Azure betreiben. Die Kombination aus Type-Safety, schlanker Syntax und nahtloser Azure-Integration macht es zum natürlichen Standard für Azure-native Teams. Wer heute ein neues Azure-Projekt startet, sollte direkt mit Bicep beginnen, nicht mit ARM-JSON oder als ARM-Krücke gedachten Workarounds.
Der nächste Schritt: Schau dir die offiziellen Bicep-Module auf GitHub an – dort gibt es fertige, gut getestete Module für die gängigsten Azure-Ressourcen, die sofort produktionsreif eingesetzt werden können.

