Overview of ARM Templates
Overview of ARM Templates

In this course, I’ll start with an overview of Azure Resource Manager templates. Then I’ll show you how to build a template from scratch and deploy an Azure Storage account with it. Next, I’ll show you how to use a template to deploy a virtual machine, which is a more complicated resource. After that, I’ll explain how to make your templates more usable by adding parameters and variables. Finally, I’ll show you how to make your templates more sophisticated by using functions.

Learning Objectives

  • Describe the structure of Azure Resource Manager templates
  • Build an ARM template and use it to deploy a resource
  • Use an ARM template to deploy a virtual machine
  • Use parameters and variables in an ARM template
  • Use functions in an ARM template

Intended Audience

  • Azure administrators and developers


  • Basic knowledge of Azure Virtual Machines, Azure Storage, and Azure Virtual Networks

If you needed to deploy one virtual machine, then you’d probably use the Azure Portal, which makes it easy. But what if you needed to deploy a hundred virtual machines? Or what if you needed to create one new VM every day, and you had to make sure they were all configured in the same way? That’s when you’d want to use an Azure Resource Manager template.

An ARM template contains all of the details that Azure needs to know to deploy a resource, such as a storage account or a virtual machine. If you want to see one, you can go to an Azure resource you’ve deployed, such as this storage account, and click “Export template”. This is the ARM template for the account.

To make it easier to read, I’m going to download it, and open it in Visual Studio Code, which is Microsoft’s free code editor. You’ll notice that it was downloaded as a zip file. That’s because it needed to download two files: the ARM template and the parameters file. I’ll tell you more about the parameters file in a bit, but for now, let’s open the template file.

As you can see, there’s a lot in here, so I’m not going to go through every line, but I’ll give you the highlights. The first line has the URL of the schema file that describes the template language. Microsoft updates the language periodically, so if you want to use the features of the latest version of the language, then you’ll need to change this URL when a new one comes out.

The content version is the version of this template file. You can set it to whatever you want, but normally, you’d initially set it to 1.0 and then update the version number when you make changes to the template.

Next, there’s a parameters section. We’ll come back to it in a minute. Then there’s a variables section, but it’s empty in this template. I’ll explain variables later. The next section, called “resources”, is the heart of an ARM template. It specifies the details of all of the resources we want to deploy. 

Each resource has a type that says what it is. The first part is called the resource provider. If you want to see a list of all of the resource providers available to you, go to your subscription in the Azure Portal and click on “Resource providers”. There’s “Microsoft.Storage”, which is the resource provider we saw in the template. If we click on it, we can see the list of its resource types in this dropdown menu. There’s “storageAccounts”.

Don’t worry if it seems like it might be hard to find what you’re looking for in this massive list of resource providers and types. I’ll show you an easier way to fill in the resource type when we build an ARM template from scratch.

Let’s get back to the resource definition. First, it gives the API version for this resource type, which determines the properties that can be set for it. Each resource type has its own specific set of properties. All resources have a name, some of them require a location, some require a sku (that is, a feature set and pricing tier), and some require a kind, such as “StorageV2” in this case, which is short for “Standard general-purpose v2 storage account”.

Now we see the resource-specific properties. These are the configuration settings for the resource. Storage accounts have lots of settings, such as whether public network access is enabled or which access tier to use by default (“Hot” in this case).

And that’s it. That’s the full definition for this storage account. But what’s the rest of this stuff down below? Well, those are actually other resource types, but really, they’re part of this storage account. You’ll see that the type for this one starts with the storage account type and ends with “blobServices”. That’s because each storage account lets you store four types of data: blobs, files, queues, and tables. So there’s one resource definition for each of those data types.

There’s another clue that these resources are connected to the storage account resource. This dependsOn element says that this resource can’t be deployed until this resource has been deployed. That makes sense because you can’t have blobs, files, queues, or tables outside of a storage account.

Notice that the part with the storage account name starts with “parameters”. Now we can see how the parameters section is used. This is the only parameter in this template. The definition starts with the name of the parameter, and then inside the curly braces, there’s a default value and a type. The type is “String”, which means that the value of this parameter must be text. The default value of the parameter is set to “camonthlyreports”, which is the name of my storage account.

So, when this template is used to deploy these resources, the value of this parameter will go here. The value is “camonthlyreports”, so that’s what it will replace this with. This might seem kind of pointless. Why wouldn’t it just put “camonthlyreports” here instead of turning it into a parameter? Well, if you wanted to use this template to create another storage account, you’d have to use a different name for the account. But you wouldn’t want to have to change every instance of that name in the template every time you deployed a new storage account using the template. By making the name a parameter, you can specify a new name on the command line, and you won’t have to modify the template.

If you only have one parameter, then setting it on the command line is a good solution, but if you have a lot of parameters, then it’s easier to set all of the values in a file and pass that parameters file on the command line. Does that sound familiar? That was the second file in the zip file we downloaded. Let’s open it to see what it looks like.

It’s pretty simple. It basically just lists the parameters that were defined in the template and lets you set a value for each one. For example, we could set the storage account’s name to “mypreciousstorage”. Make sure you put it in quotes, though, or you’ll get an error.

I’ll just mention one more thing before we move on from this template. Since storage account names have to be unique across all of Azure, why would the default value be set to the name of the existing storage account? If you tried to do a deployment using this template and you didn’t set the name parameter to something else, wouldn’t it try to use the default value and then get an error because that account name is already used? Well, no, actually. If you refer to an existing resource, then the ARM template will act on that resource, not on a new one. If you don’t change anything in the template, then nothing will happen to the resource. But if you do change something, such as a configuration detail, then it will try to make that change to the existing resource. I should warn you, though, that sometimes exported templates are not completely correct and will generate errors if used. I was quite surprised when I discovered this.

All right, I showed you how to export the ARM template for a single resource (a storage account, in this case), but what if you wanted to export an ARM template for multiple resources, such as a storage account and an App Service plan? There’s an easy way to do that. If they’re in the same resource group, then you just need to go to that resource group in the portal and export the template from there. If you only want to include some of the resources, then select the ones you want, and select “Export template” from this menu instead.

While exported templates can be useful, especially for reviewing or updating existing resources, they’re not usually the best choice for deploying new resources. One alternative is to use quickstart templates. If you search for “template”, you can choose “Deploy a custom template”.

It lists a few common templates, such as “Create a Linux virtual machine” and “Create a web app”. If you need something else, you can look for a quickstart template down here. These templates are typically created by people outside of Microsoft, so you need to use them with caution.

It can also be kind of hard to find what you’re looking for. Let’s say we want a template to create a storage account. If we type “storage”, it comes back with lots of templates, but they don’t look like what we need. We can narrow it down by typing, “storage-account”. There are still quite a few, but now we can see the one we want: “storage-account-create”.

To see it, click “Edit template”. There are a couple of interesting things to see in this one. Under this parameter for storage account type, it lists the allowed values. These are the only values that you can set this parameter to.

Something else that’s new is this outputs section at the bottom. This tells Azure what to print out after the deployment is finished. In this case, it’ll print out the storage account name and the storage account ID.

One more thing I want to point out is that the resources section is way shorter than the one in the template we looked at before. It doesn’t include anything for blobs, files, queues, or tables. It doesn’t even include any properties for the storage account itself. It only has the bare minimum details, such as the name and the location. If you don’t include all of those other details, then it just uses the defaults for all of them, so this will work just fine.

And that’s it for this overview of ARM templates.

About the Author
Learning Paths

Guy launched his first training website in 1995 and he's been helping people learn IT technologies ever since. He has been a sysadmin, instructor, sales engineer, IT manager, and entrepreneur. In his most recent venture, he founded and led a cloud-based training infrastructure company that provided virtual labs for some of the largest software vendors in the world. Guy’s passion is making complex technology easy to understand. His activities outside of work have included riding an elephant and skydiving (although not at the same time).