Understand Bicep file structure and syntax
Azure Bicep comes with its own syntax. However, it's easy to understand and follow. We won't go deep into the syntax and structure, but let's review the main concepts using an example.
Sample Bicep file
@minLength(3)
@maxLength(11)
param storagePrefix string
param storageSKU string = 'Standard_LRS'
param location string = resourceGroup().location
var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'
resource stg 'Microsoft.Storage/storageAccounts@2019-04-01' = {
name: uniqueStorageName
location: location
sku: {
name: storageSKU
}
kind: 'StorageV2'
properties: {
supportsHttpsTrafficOnly: true
}
resource service 'fileServices' = {
name: 'default'
resource share 'shares' = {
name: 'exampleshare'
}
}
}
module webModule './webApp.bicep' = {
name: 'webDeploy'
params: {
skuName: 'S1'
location: location
}
}
output storageEndpoint object = stg.properties.primaryEndpoints
Scope
The scope defines the subscription or management level that you're deploying to. You can choose from a subscription, resourceGroup, managementGroup, and tenant. In the sample file, the target scope is a resource group, which is the default deployment scope.
Available scopes:
- Resource group: Default scope for most deployments.
- Subscription: For resources that need subscription-level access.
- Management group: For enterprise-scale deployments.
- Tenant: For tenant-wide configurations.
Parameters
Parameters are used to make templates more reusable by supplying values during deployment. If you look at the sample file, you'll find storagePrefix, storageSKU, and location, all of which are used later in the file.
Parameters can have default values to simplify the process. In the sample file, the location defaults to the location of the target resource group.
Decorators
In addition to default values, decorators are used to provide extra control over the usage of the parameters. An example is the allowed decorator, which restricts certain values from being supplied. Bicep also supports other common decorators such as maxLength, minLength, maxValue, and minValue.
Common decorators:
- @allowed: Restricts values to a specific list.
- **@minLength / @maxLength:** Enforces string length constraints.
- **@minValue / @maxValue:** Enforces numeric range constraints.
- @description: Documents the parameter purpose.
- @secure: Marks sensitive values like passwords.
Variables
Like any other programming language, variables are also supported in Bicep. They provide simple name-value pairs with global scopes, which means they're accessible anywhere in the Bicep file.
Variables help:
- Avoid repetition in templates.
- Calculate values based on parameters.
- Improve template readability.
Resources
Now comes the essential part of the template: the resource. This is where you define the Azure resources to be deployed or modified as part of the deployment process. In the sample file, the resource block deploys a storage account with file services and a file share as child resources.
Parent-child relationships
With child resources being displayed differently from the JSON templates, it becomes easier to understand the parent-child relationships in the resource groups and deployment. In the sample template, you can see that the file service and file share are defined as children of the storage account, creating a clear hierarchy.
Child resource syntax:
resource parent 'Microsoft.Provider/type@version' = {
name: 'parentName'
resource child 'childType' = {
name: 'childName'
}
}
Conditional deployment
Defining resources with Bicep also supports conditions. You can deploy resources conditionally based on parameter values or other conditions.
Conditional syntax:
resource conditionalResource 'type@version' = if (condition) {
// resource definition
}
Modules
To improve code reusability and manageability, you can refer to another Bicep template as a module. Just like any other resource, you can add a condition to a module, which will evaluate to true before deploying it.
Note
Modules allow you to reuse code from a Bicep file in other Bicep files. A module is a Bicep file that's deployed from another Bicep file.
Module syntax:
module moduleName 'path/to/module.bicep' = {
name: 'deploymentName'
params: {
parameterName: parameterValue
}
}
Benefits of modules:
- Code reuse across multiple templates.
- Simplified maintenance and updates.
- Logical separation of infrastructure components.
- Easier testing and validation.
Outputs
Outputs are used to return values from a deployment, such as hostnames or IP addresses. These will be returned once a deployment is complete.
Output syntax:
output outputName string = resourceName.properties.hostname
Common uses for outputs:
- Return connection strings.
- Retrieve resource IDs for use in other deployments.
- Get dynamically assigned values like IP addresses.
- Pass values to subsequent deployment stages.
Using modules in practice
If you want truly reusable templates, you can't avoid using a module. Modules enable you to reuse a Bicep file in other Bicep files. In a module, you define what you need to deploy and any parameters needed. When you reuse it in another file, all you need to do is reference the file and provide the parameters. The rest is taken care of by Azure Bicep.
In the sample file, you're using a module that presumably is deploying a web app (webModule). The module references ./webApp.bicep and passes parameters like skuName and location.
For more information, see Using Modules in Bicep.
Working with outputs
You can use outputs to pass values from your deployment to the outside world, whether it is within a CI/CD pipeline or in a local terminal or Cloud Shell. This enables you to access values such as storage endpoints or application URLs after the deployment is finished.
All you need is the output keyword and the property you would like to access:
output storageEndpoint object = stg.properties.primaryEndpoints
In the sample file, the output returns the primary endpoints of the deployed storage account, which includes blob, file, queue, and table endpoints.
To find more information, see Outputs in Bicep.
Other features
There are many other features available within a Bicep file such as:
- Loops: Iterate over arrays to create multiple resources.
- Conditional deployment: Deploy resources based on conditions.
- Multiline strings: Define long strings across multiple lines.
- Existing resources: Reference existing Azure resources.
- Functions: Any valid function within an ARM template is also valid within a Bicep file.
Next steps
In the next unit, you'll learn how to deploy Bicep files using Azure Pipelines.