An Introduction to Azure Bicep: A Hands-On Tutorial
Introduction
In today’s cloud-driven world, managing infrastructure as code (IaC) has become essential for scalable and maintainable cloud solutions. Microsoft Azure offers several IaC tools, with Azure Bicep emerging as a powerful, simplified language for deploying resources in Azure. This tutorial will guide you through the basics of Azure Bicep, from defining resources to using modules for better organization.
What is Bicep?
Azure Bicep is a domain-specific language (DSL) for deploying Azure resources declaratively. It aims to simplify the authoring experience compared to JSON-based Azure Resource Manager (ARM) templates. Bicep files (.bicep) are transpiled into ARM JSON templates, which can then be deployed to Azure. The key benefits of Bicep include improved readability, modularity, and ease of maintenance.
How is Bicep related to ARM templates?
You might already be familiar with Azure Resource Manager templates (ARM templates), which are files that represent Azure resources. Until Bicep was available, ARM templates had to be written in a special JSON format. One common problem with JSON templates is that they’re difficult to work with because they have a complex syntax. It can be hard to get started with writing ARM templates in JSON.
Bicep solves these problems by using a much simpler language designed specifically to help you deploy resources to Azure.
Behind the scenes, Resource Manager still operates based on the same JSON templates. When you submit a Bicep template to Resource Manager, the Bicep tooling converts your template to a JSON format in a process called transpilation. This process isn’t something you typically have to think about, but you can view the JSON template file that’s created from the Bicep file.
Define Resources
In Bicep, resources are defined using a straightforward and concise syntax. Each resource has a type, name, and properties that specify its configuration. Let’s start by defining a simple Azure Storage Account.
Install
The install
command adds the Bicep CLI to your local environment. For more information, see Install Bicep tools. This command is only available through Azure CLI.
To install the latest version, use:
Azure CLI
az bicep install
To install a specific version:
Azure CLI
az bicep install --version v0.3.255
To validate your Bicep CLI installation, use:
Azure CLI
az bicep version
To upgrade to the latest version, use:
Azure CLI
az bicep upgrade
For more commands, see Bicep CLI.
Azure PowerShell doesn’t automatically install the Bicep CLI. Instead, you must manually install the Bicep CLI.
Important
The self-contained instance of the Bicep CLI installed by Azure CLI isn’t available to PowerShell commands. Azure PowerShell deployments fail if you haven’t manually installed the Bicep CLI.
When you manually install the Bicep CLI, run the Bicep commands with the bicep
syntax, instead of the az bicep
syntax for Azure CLI.
To check your Bicep CLI version, run:
Windows Command Prompt
bicep --version
Install manually
The following methods install the Bicep CLI and add it to your PATH. You must manually install for any use other than Azure CLI.
When installing manually, select a location that is different than the one managed by Azure CLI. All of the following examples use a location named bicep or .bicep. This location won’t conflict with the location managed by Azure CLI, which uses .azure.
Define Resources in a Bicep Template
To begin, you’ll need the Azure CLI and Bicep CLI installed. Create a new file named main.bicep
and add the following code to define a Storage Account:
param location string = resourceGroup().location
@minLength(3)
@maxLength(24)
param name string = 'testDemoStorageAccount'
@allowed([
'Premium_LRS'
'Premium_ZRS'
'Standard_GRS'
'Standard_LRS'
'Standard_RAGRS'
'Standard_ZRS'
])
param type string = 'Standard_LRS'
resource stacc 'Microsoft.Storage/storageAccounts@2020-08-01-preview' = {
name: name
location: location
kind: 'StorageV2'
sku: {
name: type
}
}
In this example:
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01'
defines a Storage Account resource.name
sets the name of the Storage Account, ensuring uniqueness by usinguniqueString
.location
specifies the location of the resource, set to the resource group's location.sku
andkind
define the Storage Account's SKU and kind, respectively.properties
include additional configurations likeaccessTier
.
Explanation
Parameter & Constraints Declaration
Parameters allow you to pass values into your Bicep file. This makes your deployment templates more flexible and reusable.
Location Parameter:
param location string = resourceGroup().location
- This parameter takes the location of the resource group as its default value.
Name Parameter with Constraints:
@minLength(3)
@maxLength(24)
param name string = 'testDemoStorageAccount'
This parameter declares the name of the storage account with constraints on the length (minimum 3 and maximum 24 characters).
Type Parameter with Allowed Values:
@allowed([
'Premium_LRS'
'Premium_ZRS'
'Standard_GRS'
'Standard_LRS'
'Standard_RAGRS'
'Standard_ZRS' ])
param type string = 'Standard_LRS'
This parameter defines the type of the storage account with a set of allowed values. The default value is set to ‘Standard_LRS’.
Resource Declaration
Resources in Bicep are declared using the resource
keyword, followed by the resource name, type, and API version.
- Storage Account Resource:
resource stacc 'Microsoft.Storage/storageAccounts@2020-08-01-preview' = {
name: name
location: location
kind: 'StorageV2'
sku: {
name: type
}
}
This resource declaration creates a storage account with the following properties:
name
: The name of the storage account, provided by thename
parameter.location
: The location of the storage account, provided by thelocation
parameter.kind
: The kind of storage account, set to 'StorageV2'.sku
: The SKU of the storage account, determined by thetype
parameter.
Add Flexibility by Using Parameters and Variables
To make your Bicep template more reusable, you can add parameters and variables. Parameters allow users to input values at deployment time, while variables store intermediate values.
Here, param
keywords define parameters for the Storage Account name, location, SKU, and access tier. These parameters provide flexibility and reusability to your template.
Modify main.bicep
to include parameters and variables:
Using var
for Variables
Variables in Bicep (var
) are used to store intermediate values or complex expressions, which can be reused throughout the template.
Example of Variable Declaration
var containerName = 'myContainer'
In this example, a variable named containerName
is declared and assigned the value 'myContainer'
.
Define a Blob Service and Container
To add a container to the storage account, we first define a blob service as the parent resource. Then, we add the container using the parent
property to reference the blob service.
Here’s how to do it:
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = {
parent: stacc
name: 'default'
}
resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2021-06-01' = {
parent: blobService
name: containerName
}
Explanation
- Blob Service Resource:
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = {
parent: stacc
name: 'default'
}
Here, we define a blob service as a child of the storage account (stacc
). The parent
property simplifies the relationship between the storage account and the blob service.
- Container Resource:
resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2021-06-01' = {
parent: blobService
name: containerName
}
This code defines a container as a child of the blob service. The parent
property ensures the container is correctly associated with the blob service.
This interpolation results in the full resource name path required to create the container inside the specified storage account.
Here’s an extended example that includes the use of a variable:
param location string = resourceGroup().location@minLength(3)
@maxLength(24)
param name string = 'testDemoStorageAccount'@allowed([
'Premium_LRS'
'Premium_ZRS'
'Standard_GRS'
'Standard_LRS'
'Standard_RAGRS'
'Standard_ZRS'
])
param type string = 'Standard_LRS'var containerName = 'myContainer'resource stacc 'Microsoft.Storage/storageAccounts@2020-08-01-preview' = {
name: name
location: location
kind: 'StorageV2'
sku: {
name: type
}
}resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = {
parent: stacc
name: 'default'
}resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers@2021-06-01' = {
parent: blobService
name: containerName
}
Compile the Bicep File
Use the bicep build
command to compile your Bicep file into an ARM template:
az bicep build --file .\main.bicep
This command generates a file named main.json
in the same directory, which is the ARM template equivalent of your Bicep file.
Deploy the ARM Template
1. Create a Resource Group
To create a resource group, use the az group create
command. Replace <resource-group>
with your desired resource group name and <location>
with the desired Azure region.
az group create --location westus --resource-group MyResourceGroup
2. Deploy the ARM Template
After compiling your Bicep file into an ARM template, deploy it using the az deployment group create
command.
az deployment group create --resource-group <resource-group> --template-file main.json
OR
use command
New-AzResourceGroupDeployment -TemplateFile main.bicep
note: if you get error like this
New-AzResourceGroupDeployment : The term 'New-AzResourceGroupDeployment' is not recognized as the name of
a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At line:1 char:1
+ New-AzResourceGroupDeployment -TemplateFile main.bicep
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (New-AzResourceGroupDeployment:String) [], CommandNotFoundEx
ception
+ FullyQualifiedErrorId : CommandNotFoundException
You need to install the Azure Powershell module:
You can look for just the one for this command:
Install-Module -Name Az.Resources -AllowClobber -Scope CurrentUser
Or all of them:
Install-Module -Name Az -AllowClobber -Scope CurrentUser
Group Related Resources by Using Modules
As your infrastructure grows, organizing related resources into modules improves readability and maintainability. Modules in Bicep allow you to encapsulate and reuse resource definitions.
Refactor Your Template to Use Modules
Create a new file named storage.bicep
and move the Storage Account definition into it:
param location string
param name string
@allowed([
'Premium_LRS'
'Premium_ZRS'
'Standard_GRS'
'Standard_LRS'
'Standard_RAGRS'
'Standard_ZRS'
])
param type string = 'Standard_LRS'
param containerName string
resource stacc 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: name
location: location
kind: 'StorageV2'
sku: {
name: type
}
}
resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = {
parent: stacc
name: 'default'
}
resource containers 'Microsoft.Storage/storageAccounts/blobServices/containers@2021-06-01' = {
parent: blobService
name: containerName
}
Now, update mainmodule.bicep
to use this module:
param location string = resourceGroup().location@minLength(3)
@maxLength(24)
param storageAccountName string = 'testbiceccount'param containerName string = 'imagefromimport'module storage 'storage.bicep' = {
name: 'storageModule'
params: {
location: location
name: storageAccountName
type: 'Standard_LRS'
containerName: containerName
}
}
In mainmodule.bicep
, the module
keyword imports the storage.bicep
module and passes parameters to it. This approach helps manage complex deployments by breaking them into smaller, reusable components.
3. Compile and Deploy
Compile Bicep Files
Compile both Bicep files into ARM templates:
az bicep build --file .\storage.bicep
az bicep build --file .\mainmodule.bicep
Create Resource Group and Deploy
Run the following command to create the resource group and deploy the compiled main.bicep
file:
az deployment group create --resource-group myResourceGroup --template-file main.json
Summary
Azure Bicep simplifies the process of defining, deploying, and managing Azure resources with its clean and concise syntax. By following this tutorial, you’ve learned how to:
- Define resources using Bicep.
- Add flexibility with parameters and variables.
- Organize your template with modules for better maintainability.
As you continue to explore Azure Bicep, you’ll find it a powerful tool for managing your Azure infrastructure efficiently. For more advanced scenarios, refer to the official Azure Bicep documentation.
Github repo:
Happy coding!
But wait, there’s more to explore!
In upcoming articles, I’ll delve into exciting topics like Ansible, Helm charts, and beyond. Your feedback and questions are invaluable, so feel free to share as I continue this learning adventure. Stay curious, and let’s keep building amazing things! 🚀
Thank You for reading
Please give 👏🏻 Claps if you like the blog.
Made with ❤️by Vaibhav Hariramani
- If you enjoyed this, follow me on Medium for more
- Follow me on Kaggle for more content!
- Let’s connect on LinkedIn
- Interested in collaborating?
- Check out my website.
- Check out my other website.
Don’t forget to tag us
if you find this blog beneficial for you don’t forget to share it with your friends and mention us as well. And Don’t forget to share us on Linkedin, instagram, facebook , twitter, Github
More Resources
To learn more about these Resources you can Refer to some of these articles written by Me:-
Do Checkout My other Blogs
Do find time check out my other articles and further readings in the reference section. Kindly remember to follow me so as to get notified of my publications.
Do Checkout My Youtube channel
Follow me
on Linkedin, instagram, facebook , twitter, Github
Happy coding ❤️ .