3 min read
Bicep Registry: Sharing and Reusing Infrastructure Modules
The Bicep Registry enables you to share and reuse Bicep modules across your organization. Using Azure Container Registry (ACR), you can version, publish, and consume modules just like container images.
Setting Up a Bicep Registry
Create an Azure Container Registry:
// registry.bicep
param location string = resourceGroup().location
param registryName string
resource acr 'Microsoft.ContainerRegistry/registries@2021-12-01-preview' = {
name: registryName
location: location
sku: {
name: 'Basic'
}
properties: {
adminUserEnabled: false
}
}
output registryLoginServer string = acr.properties.loginServer
Publishing Modules
Publish a module to your registry:
# Login to Azure
az login
# Publish module to registry
az bicep publish \
--file modules/storage-account.bicep \
--target br:myregistry.azurecr.io/bicep/storage-account:v1.0.0
Create a publishing script for automation:
#!/bin/bash
# publish-modules.sh
REGISTRY="myregistry.azurecr.io"
MODULES_DIR="./modules"
for module in "$MODULES_DIR"/*.bicep; do
filename=$(basename "$module" .bicep)
version=$(cat "$MODULES_DIR/$filename.version" 2>/dev/null || echo "v1.0.0")
echo "Publishing $filename:$version"
az bicep publish \
--file "$module" \
--target "br:$REGISTRY/bicep/$filename:$version"
done
Consuming Registry Modules
Use modules from your registry:
// main.bicep
param environment string
param location string = 'australiaeast'
// Use module from registry
module storageAccount 'br:myregistry.azurecr.io/bicep/storage-account:v1.0.0' = {
name: 'storage-deployment'
params: {
name: 'st${environment}${uniqueString(resourceGroup().id)}'
location: location
sku: 'Standard_LRS'
}
}
module appService 'br:myregistry.azurecr.io/bicep/app-service:v2.1.0' = {
name: 'app-deployment'
params: {
name: 'app-${environment}'
location: location
sku: environment == 'prod' ? 'P1v3' : 'B1'
}
}
output storageEndpoint string = storageAccount.outputs.primaryEndpoint
output appUrl string = appService.outputs.url
Module Aliasing
Configure aliases in bicepconfig.json:
{
"moduleAliases": {
"br": {
"myregistry": {
"registry": "myregistry.azurecr.io"
},
"publicregistry": {
"registry": "mcr.microsoft.com"
}
},
"ts": {
"myspecs": {
"subscription": "00000000-0000-0000-0000-000000000000",
"resourceGroup": "rg-template-specs"
}
}
}
}
Use aliases in your Bicep files:
// Using alias
module storage 'br/myregistry:bicep/storage-account:v1.0.0' = {
name: 'storage'
params: {
name: storageName
location: location
}
}
Creating Enterprise-Grade Modules
// modules/storage-account.bicep
@description('Name of the storage account')
@minLength(3)
@maxLength(24)
param name string
@description('Location for the storage account')
param location string = resourceGroup().location
@description('Storage account SKU')
@allowed([
'Standard_LRS'
'Standard_GRS'
'Standard_RAGRS'
'Standard_ZRS'
'Premium_LRS'
])
param sku string = 'Standard_LRS'
@description('Enable blob versioning')
param enableVersioning bool = true
@description('Enable soft delete for blobs')
param enableBlobSoftDelete bool = true
@description('Soft delete retention days')
@minValue(1)
@maxValue(365)
param softDeleteRetentionDays int = 7
@description('Resource tags')
param tags object = {}
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-08-01' = {
name: name
location: location
tags: tags
sku: {
name: sku
}
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
supportsHttpsTrafficOnly: true
allowBlobPublicAccess: false
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices'
}
}
}
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2021-08-01' = {
parent: storageAccount
name: 'default'
properties: {
isVersioningEnabled: enableVersioning
deleteRetentionPolicy: {
enabled: enableBlobSoftDelete
days: softDeleteRetentionDays
}
}
}
@description('The resource ID of the storage account')
output id string = storageAccount.id
@description('The name of the storage account')
output name string = storageAccount.name
@description('The primary blob endpoint')
output primaryEndpoint string = storageAccount.properties.primaryEndpoints.blob
@description('The primary connection string')
output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
CI/CD for Module Publishing
# .github/workflows/publish-modules.yml
name: Publish Bicep Modules
on:
push:
branches: [main]
paths:
- 'modules/**'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Get changed modules
id: changes
run: |
echo "modules=$(git diff --name-only HEAD~1 | grep '^modules/.*\.bicep$' | tr '\n' ' ')" >> $GITHUB_OUTPUT
- name: Publish changed modules
run: |
for module in ${{ steps.changes.outputs.modules }}; do
name=$(basename "$module" .bicep)
version="v1.0.${{ github.run_number }}"
az bicep publish \
--file "$module" \
--target "br:${{ secrets.ACR_NAME }}.azurecr.io/bicep/$name:$version" \
--target "br:${{ secrets.ACR_NAME }}.azurecr.io/bicep/$name:latest"
done
The Bicep Registry is essential for scaling infrastructure as code across enterprise organizations.