Overview and What You Will Learn
In this lab, you will write a simple ARM template that defines a Storage Account, validate it before deploying, deploy it, and see how the same template can be reused to deploy an identical resource again with different parameters.
Why This Matters in Production
A team manually recreates a Resource Group's worth of infrastructure after an accidental deletion, working from memory and a partially outdated wiki page, and it takes days of careful testing before they're confident the environment matches what was lost. An ARM template turns that same recovery into a single command that recreates the exact same infrastructure in minutes, because the definition itself was never lost - it lives in a file, not in someone's memory.
Core Principles
There are two approaches to defining infrastructure: imperative (a script listing every individual step to perform) and declarative (a document describing only the desired end state, leaving Azure to figure out how to get there). ARM templates are declarative.
+------------------------------------------+ +------------------------------------------+| Imperative approach | | Declarative approach (ARM) || "Create a VNet, then create a subnet, | -------> | "I want this VNet, subnet, and VM to || then create a VM..." | | exist" - Azure figures out the steps |+------------------------------------------+ +------------------------------------------+An ARM template is a JSON file with a defined structure - Parameters (values you supply at deployment time), Resources (what actually gets created), and Outputs (values returned after deployment, like a resource's generated ID).
+------------------------------------------+| template.json || parameters: storageAccountName, location|| resources: [ storage account definition]|| outputs: the account's endpoint URL |+------------------------------------------+ | v+------------------------------------------+| az deployment group create || ARM validates the ENTIRE template first, || then executes only if validation passes |+------------------------------------------+Detailed Step-by-Step Practical Lab
- Create a Resource Group for the deployment:
az group create --name rg-arm-lab-mumbai --location centralindia- Create a simple ARM template file defining a Storage Account. The actual file you save must be JSON (ARM templates are always JSON), but it's shown here as YAML to keep this guide's own formatting safe - see the note below for why:
$schema: "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"contentVersion: "1.0.0.0"parameters: storageAccountName: type: string metadata: description: "Name of the storage account to create"resources: - type: Microsoft.Storage/storageAccounts apiVersion: "2023-01-01" name: "[parameters('storageAccountName')]" location: centralindia sku: name: Standard_LRS kind: StorageV2outputs: storageEndpoint: type: string value: "[reference(parameters('storageAccountName')).primaryEndpoints.blob]"Note
"[parameters('storageAccountName')]"is ARM template function syntax - the square brackets tell ARM to evaluate this as an expression rather than treat it as a literal string, pulling in whatever value was supplied for that parameter at deployment time. When you actually create this file on disk, save it as standard JSON with curly braces exactly as ARM expects - the YAML shown above is purely to represent the same structure safely in this guide's own text.
- Save the file as
storage-template.json, then validate it before actually deploying anything:
az deployment group validate \ --resource-group rg-arm-lab-mumbai \ --template-file storage-template.json \ --parameters storageAccountName=starmlabrahul01- Once validation passes, run the actual deployment:
az deployment group create \ --resource-group rg-arm-lab-mumbai \ --template-file storage-template.json \ --parameters storageAccountName=starmlabrahul01- Reuse the exact same template to deploy a second, differently named Storage Account - demonstrating the entire point of a reusable template:
az deployment group create \ --resource-group rg-arm-lab-mumbai \ --template-file storage-template.json \ --parameters storageAccountName=starmlabrahul02- Confirm both storage accounts now exist, created from the identical template definition:
az storage account list \ --resource-group rg-arm-lab-mumbai \ --output table- Clean up:
az group delete --name rg-arm-lab-mumbai --yes --no-waitProduction Best Practices & Common Pitfalls
Common MistakeManually clicking through the Portal to build a complex environment, with no record of exactly what was created or in what order. When that environment needs to be recreated - for a new region, a disaster recovery test, or after an accidental deletion - nobody can reproduce it reliably from memory.
TipAlways run
az deployment group validatebeforeaz deployment group create. Validation checks the entire template's syntax and resource definitions before touching anything - catching a typo or a missing parameter before it becomes a partially-applied, half-broken deployment.
- Parameters make a template reusable across environments. The same template deploying a dev environment and a production environment should differ only in the parameter values supplied, not in the template file itself.
- Store templates in version control, not just on a local machine. A template sitting only on one engineer's laptop is exactly as fragile as the manual Portal-clicking process it was meant to replace.
Quick Reference & Troubleshooting Commands
| Command | Description |
|---|---|
az deployment group validate |
Check a template for errors without deploying |
az deployment group create |
Deploy a template's resources |
az deployment group list |
List past deployments to a Resource Group |
az deployment operation group list |
Show detailed status of a specific deployment |