Azure VM Image Builder — Setup Steps
Azure VM Image Builder (part of Azure Image Builder / AIB) is a managed service that automates creation of custom VM images. It wraps Packer under the hood and integrates with the Shared Image Gallery (SIG).
Prerequisites
- Azure CLI installed and logged in (
az login) - An Azure subscription with Owner or Contributor + User Access Administrator role
- Resource providers registered:
az provider register -n Microsoft.VirtualMachineImages
az provider register -n Microsoft.Storage
az provider register -n Microsoft.Compute
az provider register -n Microsoft.KeyVault
az provider register -n Microsoft.Network
Check registration status:
az provider show -n Microsoft.VirtualMachineImages -o table
Step 1: Set Environment Variables
subscriptionID=$(az account show --query id -o tsv)
imageResourceGroup=aibImageRG
location=eastus
runOutputName=aibLinuxOutput
Step 2: Create a Resource Group
az group create -n $imageResourceGroup -l $location
Step 3: Create an Identity and Permissions
Azure Image Builder needs a managed identity to distribute the built image.
identityName=aibIdentity
az identity create -g $imageResourceGroup -n $identityName
imgBuilderCliId=$(az identity show -g $imageResourceGroup -n $identityName --query clientId -o tsv)
imgBuilderId=$(az identity show -g $imageResourceGroup -n $identityName --query id -o tsv)
imgBuilderPrincipalId=$(az identity show -g $imageResourceGroup -n $identityName --query principalId -o tsv)
Create a custom role definition with the permissions AIB needs, then assign it:
cat > aibRoleImageCreation.json << EOF
{
"Name": "Azure Image Builder Image Creation Role demo",
"IsCustom": true,
"Description": "Image Builder access to create resources for the image build",
"Actions": [
"Microsoft.Compute/galleries/read",
"Microsoft.Compute/galleries/images/read",
"Microsoft.Compute/galleries/images/versions/read",
"Microsoft.Compute/galleries/images/versions/write",
"Microsoft.Compute/images/write",
"Microsoft.Compute/images/read",
"Microsoft.Compute/images/delete"
],
"AssignableScopes": [
"/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup"
]
}
EOF
az role definition create --role-definition ./aibRoleImageCreation.json
az role assignment create \
--assignee $imgBuilderPrincipalId \
--role "Azure Image Builder Image Creation Role" \
--scope /subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup
Step 4: (Optional) Create a Shared Image Gallery
sigGalleryName=aibSharedGallery
imageDefName=aibLinuxImageDef
az sig create -g $imageResourceGroup --gallery-name $sigGalleryName
az sig image-definition create \
-g $imageResourceGroup \
--gallery-name $sigGalleryName \
--gallery-image-definition $imageDefName \
--publisher aibPublisher \
--offer aibOffer \
--sku aibSku \
--os-type Linux
Step 5: Create the Image Template Configuration
Define the base image, customizations (shell scripts, restarts, file copies), and distribution target in a JSON template.
cat > helloImageTemplate.json << EOF
{
"\$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"type": "Microsoft.VirtualMachineImages/imageTemplates",
"apiVersion": "2022-02-14",
"location": "<region>",
"dependsOn": [],
"tags": {
"imagebuilderTemplate": "aibLinux",
"userIdentity": "enabled"
},
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"<imgBuilderId>": {}
}
},
"properties": {
"buildTimeoutInMinutes": 100,
"vmProfile": {
"vmSize": "Standard_D2s_v4",
"osDiskSizeGB": 30
},
"source": {
"type": "PlatformImage",
"publisher": "Canonical",
"offer": "0001-com-ubuntu-server-jammy",
"sku": "22_04-lts",
"version": "latest"
},
"customize": [
{
"type": "Shell",
"name": "InstallPackages",
"inline": [
"sudo apt-get update",
"sudo apt-get install -y nginx"
]
}
],
"distribute": [
{
"type": "SharedImageVersion",
"runOutputName": "<runOutputName>",
"artifactTags": {
"source": "azureVmImageBuilder"
},
"replicationRegions": ["<region>"],
"galleryImageId": "<sigGalleryId>"
}
]
}
}
EOF
Substitute the placeholders (<region>, <imgBuilderId>, <runOutputName>, <sigGalleryId>) with the actual resource IDs from the earlier steps, for example via sed.
Step 6: Submit the Template to Azure Image Builder
az resource create \
--resource-group $imageResourceGroup \
--properties @helloImageTemplate.json \
--is-full-object \
--resource-type Microsoft.VirtualMachineImages/imageTemplates \
-n helloImageTemplate01
Step 7: Start the Image Build
az resource invoke-action \
--resource-group $imageResourceGroup \
--resource-type Microsoft.VirtualMachineImages/imageTemplates \
-n helloImageTemplate01 \
--action Run
Step 8: Check Build Status
az image builder show \
-g $imageResourceGroup \
-n helloImageTemplate01 \
--query lastRunStatus
Step 9: Create a VM from the Built Image
Once the run status shows Succeeded, deploy a VM from the image version in the Shared Image Gallery:
az vm create \
-g $imageResourceGroup \
-n myVMFromImage \
--image "/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup/providers/Microsoft.Compute/galleries/$sigGalleryName/images/$imageDefName/versions/latest" \
--admin-username azureuser \
--generate-ssh-keys
Cleanup
az resource delete \
--resource-group $imageResourceGroup \
--resource-type Microsoft.VirtualMachineImages/imageTemplates \
-n helloImageTemplate01
az group delete -n $imageResourceGroup
