Develop Bicep Deployment Scripts with Docker and VS Code

Deployment Scripts are a feature of Bicep and ARM templates that let you run PowerShell Core or Az CLI scripts as part of your deployment. They can be a great solution if you need to create something as part of your deployment that isn’t supported in ARM, like Azure AD components, Kubernetes resources, etc. If you want to know more about using deployment scripts, look at this article.

Developing deployment scripts can be a bit of a pain. You create the script locally and test it out only to find it doesn’t work when you deploy it, or you are not sure what capabilities and libraries are available in the container used by ARM to run your script. To combat this, we can use Docker and VS Code’s remote docker execution plugin to develop and run our scripts in the exact container image used when we deploy the scripts. This should mean scripts run the same way they do in the deployment and have access to the same components.

Pre-Requites

To develop your scripts in this way, you will need a few things installed:

Configure Docker Development

Open up the project where you want to do your script development in VS Code. I tend to do this in a folder in my Bicep project, but you don’t have to.

We need to create a configuration file that tells VS Code what container to run our development environment in. Create a folder in your project called .devcontainer in here create a file called devcontainer.json. The folder and file must be called these names.

This file tells VS Code how to create and launch the container used for development. You can do all sorts of complex things in this file; you can have VS Code build the container from a local docker file, install software, etc. For our needs, we don’t need to build an image; we need to pull in the images that Microsoft has already created for use with deployment scripts:

• For PowerShell mcr.microsoft.com/azuredeploymentscripts-Powershell:az
• For Azure CLI - mcr.microsoft.com/azure-CLI:

is the version of the Azure PowerShell or Azure CLI libraries you want to use, so if I wanted to use version 7.3 of the Az PowerShell cmdlets, I would use:

mcr.microsoft.com/azuredeploymentscripts-powershell:az7.3


For version 2.34 of the Azure CLI, I would use:

mcr.microsoft.com/azure-cli:2.34


Once you have selected the version of the image you want to use, we need to add it to the devcontainer.json file. Open this file and add the following:

{
"name": "Deployment Scripts",
"image": "<image name>"",

}


The name can be anything you want to identify this configuration; image is the name of the image you selected above to run your chosen CLI. So for AZ PowerShell 7.4, this would look like this:

{
"name": "Deployment Scripts",
"image": "mcr.microsoft.com/azuredeploymentscripts-powershell:az7.3",
}


This is the bare minimum we need. This will launch a dev environment running this image that we can run and test our scripts in. However, you need to bear in mind that VS Code runs entirely in the context of this Docker image, so any VS Code extensions you had installed on your local instance won’t be present. Given this, you may want to have it install some extensions for you, which you can do with the extensions setting. This is just an array of the names of the extensions you want to install. You need the full name of the extension, which you can find on the extensions marketplace page. Below I am installing the PowerShell extensions.

{
"name": "Deployment Scripts",
"image": "mcr.microsoft.com/azuredeploymentscripts-powershell:az7.3",
"extensions": ["ms-vscode.powershell"]
}


Other options allow you to customers things further, such as changing VS Code settings. You can find the full details of all these options here.

Develop in Docker

Now you have your dev container settings configured, you are ready to launch your container. In VS Code, go to the button in the bottom left labelled “Open a remote window”:

In the window that opens, select the “Reopen in container” option:

Once you click on this VS Code will download the required image and configure it for remote execution. This can take a while the first time you do it. If you look at the bottom right, you should see an icon indicating progress and allowing you to view the log.

Once this completes, it will show as running, and you will now be working in the dev container.

From this point on, you can use VS Code, as usual, browse, edit and save files, run and debug scripts, etc. All of this will run in the context of the container and use any applications or libraries in the container. The files from your project are mounted as a volume so that you can edit them in the container, but they will still be saved back to your local machine and not lost.

If you want to go back to developing locally (not in a container), click the same button in the bottom left and go to “Reopen locally”.

A Note on Authentication

When running deployment scripts in an actual deployment, you have the option to use managed identity to authenticate to Azure resources. When you run locally, managed identity will not work, so you will need to either manually authenticate at the command line inside the container or authenticate in your script using a service principal or similar. You can switch to managed identity when you deploy for real.