Create an Azure Container Registry(ACR) in Azure for Bicep Modules
Hi and welcome. Today I thought I might brush up on some best practices for Bicep modules and create a little handy guide for reference.
If you’re working with Bicep modules in a professional or enterprise environment, using a private container registry is a best practice for keeping your modules . It ensures immutability, security, and easy consumption of modules across your teams. In this guide, I'll walk through creating an Azure Container Registry (ACR), publishing a basic bicep file to it, and validating the setup.
Why Use a Private Bicep Module Registry?
You might be wondering, why go through all the extra steps of pushing modules into a regisry when I could just store them in Git?
Here are the main reasons:
- Immutability - Once a module version is published (e.g.,
v1.0.0), it can’t be changed, ensuring reproducible deployments. - Consistency across teams -Multiple projects and teams can consume the same module versions directly from a trusted source.
- Security & Access Control - You can enforce role-based access and network restrictions using ACR.
- Better CI/CD integration - Pipelines can automatically publish validated modules, making them instantly available for others.
- Support for restricted environments - Works well in air-gapped or enterprise setups where direct GitHub access may be limited.
Prerequisites
Before you begin, make sure you have:
- Logged in to Azure CLI
- Bicep CLI installed
- An existing Resource Group in Azure
- Permissions to push to your ACR
Step 1: Create a Bicep File for Your Registry
Start by creating a Bicep file (e.g., acr.bicep) that defines your Azure Container Registry. This file will contain the configuration for your registry, including its name, SKU, and location.
This file is just a sample file I pulled from the an azure link to create a azure container registry
@minLength(5)
@maxLength(50)
@description('Provide a globally unique name of your Azure Container Registry')
param acrName string = 'acr${uniqueString(resourceGroup().id)}'
@description('Provide a location for the registry.')
param location string = resourceGroup().location
@description('Provide a tier of your Azure Container Registry.')
param acrSku string = 'Basic'
resource acrResource 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = {
name: acrName
location: location
sku: {
name: acrSku
}
properties: {
adminUserEnabled: false
}
}
@description('Output the login server property for later use')
output loginServer string = acrResource.properties.loginServer
Step 2: Deploy the Registry
Run the following command in PowerShell or your terminal to deploy your registry:
az deployment group create --resource-group example-resources --template-file acr.bicep --parameters acrName=acrtestingaustraliaeast123

Step 3: Validate Your Registry
Once deployment is complete, check that your registry is available and get the login server URL:
Get-AzContainerRegistry -ResourceGroupName "example-resources" -Name "acrtestingaustraliaeast123" | Select-Object LoginServer


Step 4: Publish Bicep Modules to the Registry
Now that the registry is ready, you can publish your modules. For example:
az bicep publish --file .\modules\container-registry.bicep --target "br:acrtestingaustraliaeast123.azurecr.io/bicep/modules/acr:v1" --documentation-uri "https://www.contoso.com/exampleregistry.html" --with-source
Notes:
- The
--with-sourceflag publishes the source code alongside the compiled module. - The
--documentation-uriparameter links to any additional documentation for your module.
the source parameter publishes the source code

Step 5: Verify in the Azure Portal
To confirm everything worked:
- Navigate to your Azure Container Registry in the Azure Portal.
- Go to Repositories.
- You should see your published module under the path
bicep/modules/acrwith the tagv1.
Your private Bicep module is now ready to be consumed securely in other deployments!

Step 6: Consume the Module in Another Bicep File
Ok great, now that your module is published, you can reference it in your bicep deployments using the bicep reigstry syntax
What’s happening here?
- The
br:prefix tells Bicep to pull the module from a registry. - The path points to your private ACR instance.
- The version tag (
:v1) ensures you always get the exact version you published.
module myAcrModule 'br:acrtestingaustraliaeast123.azurecr.io/bicep/modules/acr:v1' = {
name: 'acrDeployment'
params: {
acrName: 'myNewRegistry'
location: 'australiaeast'
sku: 'Basic'
}
}
Run it with the below command:
az deployment group create --resource-group example-resources --template-file main.bicep
And that's it. Easy as that, you've succesfully deployed an Azure Container Registry for Bicep Modules
What’s next?
From here, you can:
- Tag and version your modules for better lifecycle management.
- Integrate them directly into your CI/CD pipelines.
- Add documentation so your team knows how to use each module.
- Secure your registry with RBAC to control who can publish and consume modules.
- And of course, always test thoroughly before pushing to production.
References & Quickstart Links:

