As technology has evolved, so have the tools we can use to build (or rebuild!) standard, repeatable system configurations. I remember building my first Windows-based computer systems using an “answer file” to populate and bypass the “out of the box” configuration experience prompts – speeding up the build process by removing the user interaction steps and standardizing the build of the systems.
As you become familiar with Azure, it’s common to start with the Azure portal for creating virtual machines, then explore Azure Resource Manager templates. These templates are written using JSON – a file format that lets us store information about how we want system to be configured (e.g. region = eastus) that Azure then refers to in the build process. Azure Bicep is an evolution of that – it’s a language with a more more concise syntax (rules or structure) but in the background it compiles into a standard ARM template for deployment.
Learning Azure Bicep has been on my to-do list, but I’ve had other priorities. So I was thrilled to hear that a new series of learning paths for Azure Bicep have been released on Microsoft Learn – and I jumped right in!
Before you start: It helps to have a prior understanding of ARM templates. You can view the JSON of an existing virtual machine from the Azure portal, and see how the configuration settings are displayed in JSON format.
Or check out the Deploy and manage resources in Azure by using JSON ARM templates learning path.
Note: You do not need to know Azure DevOps or Git.
Fundamentals of Bicep
The Fundamentals of Bicep learning path starts off with an explanation of the concept “infrastructure as code” or IaC and it’s benefits. I’m always intrigued when we get to code explanations because many of the terms that software developers “grow up with” (like source control, versioning, declarative syntax, compiling) can be foreign jargon to IT Pros who come from a land of Kix32 scripts or System Center Configuration Manager. The first module does a good job of explaining IaC, including the difference between imperative and declarative code, without making incorrect assumptions about my existing coding knowledge! It uses a few software development comparisons though, but they’re explained well.
There’s an overview of what Azure Resource Manager is, and you learn that Bicep is a type of ARM template, with the Bicep language being an alternative to using the JSON language syntax. Later, you learn that when you submit a Bicep template to Azure Resource Manager, it actually converts to JSON before executing.
This one image comparing an Azure Bicep file to a JSON file for the same resource, was enough to make me want to learn more!
And, you can even “decompile” it in reverse – use a command to translate a JSON-based ARM template into Bicep.
Overall, the first module gives you a good idea of what Bicep is and why you would use it, without exploring any of the Bicep language yet.
You’ll need Visual Studio Code, the Bicep extension and Azure CLI or Azure PowerShell, all installed locally, and you’re given the links to download them. Visual Studio Code is a great text editor for code and the Bicep extension color-codes your text based on the syntax of the Bicep language and highlights errors. You don’t need your own Azure subscription though! The exercise is done in a temporary, disposable Microsoft Learn Sandbox environment. However, the learning module itself won’t check and validate the successful deployment of your resources.
Our sample architecture includes Azure App Service and a storage account, for a website. You don’t need to be familiar with these services to follow along with how to define their configuration using Bicep.
Now you’ll learn about resource definitions, parameters, variables, expressions, modules and outputs.
The module gives you both sample code and an explanation of how that code is made up. Even though we’ve learnt that we don’t need to explicitly state each step in the build process, we may be creating resources that are dependant on each other and need to be created in the right order. You learn how to use Bicep’s symbolic name to grab a property from a previous resource (in this case, the resource ID of the App Service Plan) and use it in the deployment of the App Service App.
Exercise time! I chose PowerShell as I use that more often than I use the Azure CLI. I arranged my browser window and Visual Studio Code side by side on my monitor so I could follow along. This exercise even suggests that you type the code instead of copying & pasting it, so you can see how the extension helps. As well as color-coding, Visual Studio Code automatically added end makes like ‘ and } as I typed out the Bicep details and automatically indented lines.
Tip: Many Azure resources need a globally unique name, so to minimize the risk of a duplicate with other people using the name in this exercise, they suggest changing it. I use the current date as part of my unique resource name if it’s something that will be deleted anyway. The sandbox will automatically expire & cease to exist, but even in my own subscriptions this is a good visual reminder of when I created something, and the fact I was only expecting it to be a temporary thing that could be deleted.
Next, you can bring up a PowerShell interface right in Visual Studio Code, with the Terminal. This is where my old-school DOS knowledge helped, as my prompt was in a subdirectory of my Scripts folder and I navigated to a different subfolder called Bicep by typing “cd ../Bicep” (I love that those cd change directory commands work in PowerShell too!).
Before you connect to Azure and deploy your resource, you also need the Bicep CLI, and there’s a link to install it. I copied & pasted a set of PowerShell commands right into my Visual Studio Code terminal and saw the Bicep help displayed at the end, which confirmed it installed successfully.
After connecting to Azure with Connect-AzAccount, I needed to Set-AzContext “Concierge Subscription” which tells this session which subscription I want to query or act on – as my Azure account has a few different subscriptions. Concierge Subscription is the name of the temporary sandbox environment, and the exercise steps explain this.
Then, after setting the Resource Group so you don’t have to go back and add the resource group’s unique name to your template file, you run the New-AzResourceGroupDeployment command and reference your main.bicep file as the template. The output in your Terminal window should include ProvisioningState: Succeeded, once the deployment completes.
You can also check in the Azure Portal if your new storage account has appeared, and the exercise reminds you to switch to the Microsoft Learn Sandbox Directory before you can see the Concierge Subscription and its resources. Or you can run the provided Get-AzResourceGroupDeployment command to list the deployment and it’s provisioning state.
Finally, you add the App Service plan and the App Service app to your Bicep template and run the deployment again.
Add flexibility by using parameters and variables
The next unit explains that parameters are provided from outside of the template file, and you can store them in a parameters file (like our answers file for operating system configuration). They are likely to be things you will change with each deployment – resource names, locations, pricing tiers etc. Variables are defined inside the template file, allowing for easy reuse of a variable’s value.
Parameters remind me a little of registry entries – a key name, a key value and a key type – only this time it’s a parameter name, a parameter type (string for text, int for numbers, bool for Boolean true/false) and you can provide a default value.
Variables don’t need a type and you provide the variable name and its value inside your template, then refer to the variable whereever you need it.
You can also use parameters to query the properties of an existing resource and use that value elsewhere in your template. For example, you can fetch the location of a resource group and set that location to be used in each resource you are creating. This felt familiar to me from some very basic software coding principles, but it was good to see them explained so clearly in the context of Bicep. If you have more of a software development background, you might pick this up pretty easily and skim through it.
Now you get into more complicated expressions, using uniqueString to name resources and combining strings to make those names more meaningful. And you learn how to ask for a parameter value, specify a list of what values are allowed, then set the variable values based on that input. Today I learned “?” is used in an “if/then” statement!
Exercise time! Let’s add parameters and variables to the Bicep template.
You’ll be using the same sandbox environment and main.bicep file from earlier, and you can see how adding the parameters and variables lets you remove hard-coded values like name, location and SKU.
To finish this learning module, you learn about outputs and Bicep modules.
Outputs let Bicep display a value at the end of the deployment based on the resources you have created. For example, you might want it to return the new public IP address. These outputs could then be used in the next part of a deployment pipeline.
Modules let you break up your Bicep template into reusable, referenceable pieces – not usually one module per resource, but a small group of resources that make sense to be deployed together, but could be used in different resource deployments. You’ll also get an exercise where you break up your original Bicep template, moving the AppService resources into their own module and adding outputs. If you’ve seen any errors so far, you’ll be pleased to see a full list of what the final files should look like.
The knowledge check questions test your understanding of parameters, variables, expressions and outputs. They require you to read and understand each of the multi-choice options provided. If you get them wrong, you’ll be provided with an explanation as to why your answer wasn’t correct, and you can try again. Like all MS Learn modules, you’ll get bonus XP points if you get all the answers correct on the first try.
But wait, there’s more!
So far that only covers the first two modules of the Fundamentals learning path, which also includes:
Each module will take an estimated 30-45mins to complete, but even the first two give you a nice basic understanding to move on from, and build on those early concepts. I’m interested in learning more, and I can see how defining these files would make it easy for me to deploy, delete and redeploy resources that I use infrequently for demos. I know many people have that set up with ARM templates already.
After the Fundamentals
There are two additional learning paths to extend your Bicep knowledge, especially if you work in a team of people or across more complex environments:
Intermediate Bicep – This learning path covers child and extension resources, managing changes to your code using Git, structuring your Bicep code for collaboration, previewing Azure deployment changes by using what-if, and migrating Azure resource and JSON ARM templates to Bicep.
Advanced Bicep – This learning path explores deploying resources to other subscriptions, management groups and tenants, extending ARM templates by using deployment scripts and publishing libraries of reusable infrastructure code with template specs.
Are you using Azure Bicep? Have you noticed the difference from JSON? Did you find it easy to learn if you don’t have a software development background? Let us know in the comments!
Also check out: