The concepts behind ARM templates are important ones - infrastructure as code, parameterized deployments, desired-state delivery. But the JSON format is difficult to work with, especially for larger applications with multiple resources.
The evolution of ARM is a new tool called Bicep, which uses a custom language to define resources in a simpler and more manageable template.
Here’s a snippet of Bicep for defining a Storage Account:
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' = {
name: storageAccountName
location: location
sku: {
name: storageSku
}
kind: 'StorageV2'
properties: {
supportsHttpsTrafficOnly: httpsOnly
}
}
The resource type specifies the version of the schema its using, but the rest of the template storage-account/main.bicep is much more readable than the JSON alternative:
location
and storageSku
)Bicep is a much friendlier language to use. You can deploy Bicep files directly or you can generate ARM JSON files from the Bicep. You don’t need any additional tools to deploy Bicep files.
📋 Create a resource group labs-arm-bicep
and use a deployment group create
command to deploy the Bicep file in labs/arm-bicep/storage-account/main.bicep
.
Not sure how?</summary>
az group create -n labs-arm-bicep --tags courselabs=azure --location westeurope
This will request parameter values from the CLI:
az deployment group create -g labs-arm-bicep --template-file labs/arm-bicep/storage-account/main.bicep
Or supply the values in the command:
az deployment group create -g labs-arm-bicep --template-file labs/arm-bicep/storage-account/main.bicep --parameters storageAccountName=<unique-name>
</details>
The output from the deployment command is the same for JSON and Bicep specs.
What-if support is there too - run this command with a different SKU parameter but the same account name, and the output will tell you what would change:
az deployment group create -g labs-arm-bicep --template-file labs/arm-bicep/storage-account/main.bicep --what-if --parameters storageSku=Standard_GRS storageAccountName=<unique-name>
Bicep is the preferred way of using ARM, but it’s more recent than the JSON templates - so lots of projects will still use JSON. With the Bicep tools you can generate Bicep files from JSON specs and vice versa, which means you can define your infrastructure with more manageable Biceps, but continue using the existing ARM workflow.
You can install Bicep tools directly from the CLI:
az bicep install
# the bicep commands have their own help text:
az bicep --help
If that doesn’t work for you try another Bicep installation option
This ARM spec is for the same Linux VM in the ARM lab - all the resources are defined in JSON format:
📋 Use the Bicep CLI to generate a Bicep file from the JSON.
Not sure how?</summary>
The decompile
command generates Bicep from ARM:
az bicep decompile --help
az bicep decompile -f labs/arm-bicep/vm-simple-linux/azuredeploy.json
</details>
You should have a file generated in labs/arm-bicep/vm-simple-linux/azuredeploy.bicep
. Check that file and you’ll see:
Run a what-if deployment from the generated Bicep file to check that it is valid:
az deployment group create -g labs-arm-bicep --template-file labs/arm-bicep/vm-simple-linux/azuredeploy.bicep --what-if --parameters adminUsername=linuxuser adminPasswordOrKey=<strong-password>
You’ll see output for all the resources to be created, and you may see warnings about the generated template.
📋 Fix the warnings in the Bicep file and update the NIC to use the static IP 10.1.0.103
- then deploy the template.
Not sure how?</summary>
Here’s an example of the updated file:
The sets the same privateIP values we used in the ARM lab.
az deployment group create -g labs-arm-bicep --template-file labs/arm-bicep/vm-simple-linux/azuredeploy-updated.bicep --parameters adminUsername=linuxuser adminPasswordOrKey=<strong-password>
</details>
You should find the Bicep file much easier to navigate and edit.
Bicep templates are typically meant to describe all the resources in the Resource Group.
The default deployment mode for ARM is incremental which means any new resources in the template get added, any matching ones are left as they are, and anything extra in the Resource Group (not described in the template) is left as-is.
The resource identifiers have been tidied up from the generated Bicep, but the specs are the same.
Run a what-if deployment and you’ll see three new resources to be added and no changes to the existing resources:
az deployment group create -g labs-arm-bicep --template-file labs/arm-bicep/vm-and-sql-db/main.bicep --parameters adminUsername=linuxuser adminPasswordOrKey=<strong-password> sqlAdminPassword=<strong-password> --what-if
Bicep templates have very clear inputs and outputs. A common maintenance task is to move fixed settings in the template to parameters to make the deployment more flexible.
Update the Bicep template in vm-and-sql-db/main.bicep
to make two settings configurable:
Basic
or Standard
AdventureWorksLT
or WideWorldImportersStd
Remember you need to delete the Resource Groups, not the deployment:
az group delete -y --no-wait -n labs-arm-bicep
az group delete -y --no-wait -n labs-arm-bicep-lab