Create a Windows VM by using Azure VM Image Builder
Applies to: ✔️ Windows VMs
In this article, you learn how to create a customized Windows image by using Azure VM Image Builder. The example in this article uses customizers for customizing the image:
- PowerShell (ScriptUri): Download and run a PowerShell script.
- Windows Restart: Restarts the VM.
- PowerShell (inline): Runs a specific command. In this example, it creates a directory on the VM by using
mkdir c:\\buildActions
. - File: Copies a file from GitHub to the VM. This example copies index.md to
c:\buildArtifacts\index.html
on the VM. buildTimeoutInMinutes
: Specifies a build time, in minutes. The default is 240 minutes, which you can increase to allow for longer-running builds. The minimum allowed value is 6 minutes. Values shorter than 6 minutes will cause errors.vmProfile
: Specifies avmSize
and network properties.osDiskSizeGB
: Can be used to increase the size of an image.identity
. Provides an identity for VM Image Builder to use during the build.
Use the following sample JSON template to configure the image: helloImageTemplateWin.json.
Register the providers
To use VM Image Builder, you need to register the feature. Check your registration by running the following commands:
az provider show -n Microsoft.VirtualMachineImages | grep registrationState
az provider show -n Microsoft.KeyVault | grep registrationState
az provider show -n Microsoft.Compute | grep registrationState
az provider show -n Microsoft.Storage | grep registrationState
az provider show -n Microsoft.Network | grep registrationState
az provider show -n Microsoft.ContainerInstance -o json | grep registrationState
If the output doesn't say registered, run the following commands:
az provider register -n Microsoft.VirtualMachineImages
az provider register -n Microsoft.Compute
az provider register -n Microsoft.KeyVault
az provider register -n Microsoft.Storage
az provider register -n Microsoft.Network
az provider register -n Microsoft.ContainerInstance
Set variables
Because you'll be using some pieces of information repeatedly, create some variables to store that information:
# Resource group name - we're using myImageBuilderRG in this example
imageResourceGroup='myWinImgBuilderRG'
# Region location
location='ChinaNorth3'
# Run output name
runOutputName='aibWindows'
# The name of the image to be created
imageName='aibWinImage'
Create a variable for your subscription ID:
subscriptionID=$(az account show --query id --output tsv)
Create the resource group
To store the image configuration template artifact and the image, use the following resource group:
az group create -n $imageResourceGroup -l $location
Create a user-assigned identity and set permissions on the resource group
VM Image Builder uses the provided user-identity to inject the image into the resource group. In this example, you create an Azure role definition with specific permissions for distributing the image. The role definition is then assigned to the user identity.
Create a user-assigned managed identity and grant permissions
Create a user-assigned identity so that VM Image Builder can access the storage account where the script is stored.
identityName=aibBuiUserId$(date +'%s')
az identity create -g $imageResourceGroup -n $identityName
# Get the identity ID
imgBuilderCliId=$(az identity show -g $imageResourceGroup -n $identityName --query clientId -o tsv)
# Get the user identity URI that's needed for the template
imgBuilderId=/subscriptions/$subscriptionID/resourcegroups/$imageResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$identityName
# Download the preconfigured role definition example
curl https://raw.githubusercontent.com/azure/azvmimagebuilder/master/solutions/12_Creating_AIB_Security_Roles/aibRoleImageCreation.json -o aibRoleImageCreation.json
imageRoleDefName="Azure Image Builder Image Def"$(date +'%s')
# Update the definition
sed -i -e "s%<subscriptionID>%$subscriptionID%g" aibRoleImageCreation.json
sed -i -e "s%<rgName>%$imageResourceGroup%g" aibRoleImageCreation.json
sed -i -e "s%Azure Image Builder Service Image Creation Role%$imageRoleDefName%g" aibRoleImageCreation.json
# Create role definitions
az role definition create --role-definition ./aibRoleImageCreation.json
# Grant a role definition to the user-assigned identity
az role assignment create \
--assignee $imgBuilderCliId \
--role "$imageRoleDefName" \
--scope /subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup
Download the image configuration template
We've created a parameterized image configuration template for you to try. Download the example JSON file, and then configure it with the variables that you set earlier.
curl https://raw.githubusercontent.com/azure/azvmimagebuilder/master/quickquickstarts/0_Creating_a_Custom_Windows_Managed_Image/helloImageTemplateWin.json -o helloImageTemplateWin.json
sed -i -e "s%<subscriptionID>%$subscriptionID%g" helloImageTemplateWin.json
sed -i -e "s%<rgName>%$imageResourceGroup%g" helloImageTemplateWin.json
sed -i -e "s%<region>%$location%g" helloImageTemplateWin.json
sed -i -e "s%<imageName>%$imageName%g" helloImageTemplateWin.json
sed -i -e "s%<runOutputName>%$runOutputName%g" helloImageTemplateWin.json
sed -i -e "s%<imgBuilderId>%$imgBuilderId%g" helloImageTemplateWin.json
You can modify this example in the terminal by using a text editor such as vi
.
vi helloImageTemplateWin.json
Note
For the source image, always specify a version. You can't specify latest
as the version.
If you add or change the resource group that the image is distributed to, make sure that the permissions are set on the resource group.
Create the image
Submit the image configuration to the VM Image Builder service by running the following commands:
az resource create \
--resource-group $imageResourceGroup \
--properties @helloImageTemplateWin.json \
--is-full-object \
--resource-type Microsoft.VirtualMachineImages/imageTemplates \
-n helloImageTemplateWin01
When you're done, a success message is returned to the console, and a VM Image Builder configuration template is created in the $imageResourceGroup
. To view this resource in the resource group, go to the Azure portal, and then enable Show hidden types.
In the background, VM Image Builder also creates a staging resource group in your subscription. This resource group is used to build the image in the following format: IT_<DestinationResourceGroup>_<TemplateName>
.
Note
Don't delete the staging resource group directly. First, delete the image template artifact, which causes the staging resource group to be deleted.
If the service reports a failure when you submit the image configuration template, do the following:
- See Troubleshoot the Azure VM Image Builder service.
- Before you try to resubmit the template, delete it by running the following commands:
az resource delete \
--resource-group $imageResourceGroup \
--resource-type Microsoft.VirtualMachineImages/imageTemplates \
-n helloImageTemplateWin01
Start the image build
Start the image-building process by using az resource invoke-action.
az resource invoke-action \
--resource-group $imageResourceGroup \
--resource-type Microsoft.VirtualMachineImages/imageTemplates \
-n helloImageTemplateWin01 \
--action Run
Wait until the build is complete.
If you encounter any errors, see Troubleshoot the Azure VM Image Builder service.
Create the VM
Create the VM by using the image that you built. In the following code, replace <password> with your own password for the aibuser on the VM.
az vm create \
--resource-group $imageResourceGroup \
--name aibImgWinVm00 \
--admin-username aibuser \
--admin-password <password> \
--image $imageName \
--location $location
Verify the customization
Create a Remote Desktop connection to the VM by using the username and password that you set when you created the VM. In the VM, open a Command Prompt window, and then type:
dir c:\
The following two directories are created during the image customization:
- buildActions
- buildArtifacts
Clean up your resources
When you're done, delete the resources you've created.
Delete the VM Image Builder template.
az resource delete \ --resource-group $imageResourceGroup \ --resource-type Microsoft.VirtualMachineImages/imageTemplates \ -n helloImageTemplateWin01
Delete the role assignment, role definition, and user identity.
az role assignment delete \ --assignee $imgBuilderCliId \ --role "$imageRoleDefName" \ --scope /subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup az role definition delete --name "$imageRoleDefName" az identity delete --ids $imgBuilderId
Delete the image resource group.
az group delete -n $imageResourceGroup
Next steps
To learn more about the components of the JSON file that this article uses, see the VM Image Builder template reference.