The azure-native:compute:Image resource, part of the Pulumi Azure Native provider, defines a managed VM image that captures OS and data disk configurations for reuse across VM deployments. This guide focuses on four capabilities: capturing images from running VMs, converting VHD blobs and managed disks to images, including data disks in multi-volume images, and applying customer-managed encryption.
Images reference existing VMs, VHD blobs, managed disks, or snapshots. They may require DiskEncryptionSets for customer-managed encryption. The examples are intentionally small. Combine them with your own VM preparation workflows and encryption policies.
Capture an image from a running VM
Teams often need to replicate VM configurations across environments or create golden images from customized VMs. Azure allows you to capture a generalized VM as an image.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const image = new azure_native.compute.Image("image", {
imageName: "myImage",
location: "West US",
resourceGroupName: "myResourceGroup",
sourceVirtualMachine: {
id: "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM",
},
});
import pulumi
import pulumi_azure_native as azure_native
image = azure_native.compute.Image("image",
image_name="myImage",
location="West US",
resource_group_name="myResourceGroup",
source_virtual_machine={
"id": "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM",
})
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewImage(ctx, "image", &compute.ImageArgs{
ImageName: pulumi.String("myImage"),
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
SourceVirtualMachine: &compute.SubResourceArgs{
Id: pulumi.String("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var image = new AzureNative.Compute.Image("image", new()
{
ImageName = "myImage",
Location = "West US",
ResourceGroupName = "myResourceGroup",
SourceVirtualMachine = new AzureNative.Compute.Inputs.SubResourceArgs
{
Id = "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Image;
import com.pulumi.azurenative.compute.ImageArgs;
import com.pulumi.azurenative.compute.inputs.SubResourceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var image = new Image("image", ImageArgs.builder()
.imageName("myImage")
.location("West US")
.resourceGroupName("myResourceGroup")
.sourceVirtualMachine(SubResourceArgs.builder()
.id("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM")
.build())
.build());
}
}
resources:
image:
type: azure-native:compute:Image
properties:
imageName: myImage
location: West US
resourceGroupName: myResourceGroup
sourceVirtualMachine:
id: /subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM
The sourceVirtualMachine property points to an existing VM by its resource ID. The VM must be in a generalized state before capture: run sysprep on Windows or waagent deprovision on Linux. Once captured, the image can deploy identical VMs across regions or subscriptions.
Create an image from a VHD blob
Organizations migrating from on-premises or other clouds often have VHD files stored in Azure Blob Storage. These VHDs can be converted into managed images for VM deployment.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const image = new azure_native.compute.Image("image", {
imageName: "myImage",
location: "West US",
resourceGroupName: "myResourceGroup",
storageProfile: {
osDisk: {
blobUri: "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
osState: azure_native.compute.OperatingSystemStateTypes.Generalized,
osType: azure_native.compute.OperatingSystemTypes.Linux,
},
zoneResilient: true,
},
});
import pulumi
import pulumi_azure_native as azure_native
image = azure_native.compute.Image("image",
image_name="myImage",
location="West US",
resource_group_name="myResourceGroup",
storage_profile={
"os_disk": {
"blob_uri": "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
"os_state": azure_native.compute.OperatingSystemStateTypes.GENERALIZED,
"os_type": azure_native.compute.OperatingSystemTypes.LINUX,
},
"zone_resilient": True,
})
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewImage(ctx, "image", &compute.ImageArgs{
ImageName: pulumi.String("myImage"),
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
StorageProfile: &compute.ImageStorageProfileArgs{
OsDisk: &compute.ImageOSDiskArgs{
BlobUri: pulumi.String("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd"),
OsState: compute.OperatingSystemStateTypesGeneralized,
OsType: compute.OperatingSystemTypesLinux,
},
ZoneResilient: pulumi.Bool(true),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var image = new AzureNative.Compute.Image("image", new()
{
ImageName = "myImage",
Location = "West US",
ResourceGroupName = "myResourceGroup",
StorageProfile = new AzureNative.Compute.Inputs.ImageStorageProfileArgs
{
OsDisk = new AzureNative.Compute.Inputs.ImageOSDiskArgs
{
BlobUri = "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
OsState = AzureNative.Compute.OperatingSystemStateTypes.Generalized,
OsType = AzureNative.Compute.OperatingSystemTypes.Linux,
},
ZoneResilient = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Image;
import com.pulumi.azurenative.compute.ImageArgs;
import com.pulumi.azurenative.compute.inputs.ImageStorageProfileArgs;
import com.pulumi.azurenative.compute.inputs.ImageOSDiskArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var image = new Image("image", ImageArgs.builder()
.imageName("myImage")
.location("West US")
.resourceGroupName("myResourceGroup")
.storageProfile(ImageStorageProfileArgs.builder()
.osDisk(ImageOSDiskArgs.builder()
.blobUri("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd")
.osState("Generalized")
.osType("Linux")
.build())
.zoneResilient(true)
.build())
.build());
}
}
resources:
image:
type: azure-native:compute:Image
properties:
imageName: myImage
location: West US
resourceGroupName: myResourceGroup
storageProfile:
osDisk:
blobUri: https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd
osState: Generalized
osType: Linux
zoneResilient: true
The storageProfile defines the OS disk source. The blobUri points to your VHD file in blob storage. The osState must be Generalized, and osType specifies Linux or Windows. The zoneResilient property enables zone-redundant storage for higher availability.
Create an image from a managed disk
When you have a managed disk containing a generalized OS, you can create an image directly from it without needing intermediate blob storage.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const image = new azure_native.compute.Image("image", {
imageName: "myImage",
location: "West US",
resourceGroupName: "myResourceGroup",
storageProfile: {
osDisk: {
managedDisk: {
id: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk",
},
osState: azure_native.compute.OperatingSystemStateTypes.Generalized,
osType: azure_native.compute.OperatingSystemTypes.Linux,
},
zoneResilient: true,
},
});
import pulumi
import pulumi_azure_native as azure_native
image = azure_native.compute.Image("image",
image_name="myImage",
location="West US",
resource_group_name="myResourceGroup",
storage_profile={
"os_disk": {
"managed_disk": {
"id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk",
},
"os_state": azure_native.compute.OperatingSystemStateTypes.GENERALIZED,
"os_type": azure_native.compute.OperatingSystemTypes.LINUX,
},
"zone_resilient": True,
})
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewImage(ctx, "image", &compute.ImageArgs{
ImageName: pulumi.String("myImage"),
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
StorageProfile: &compute.ImageStorageProfileArgs{
OsDisk: &compute.ImageOSDiskArgs{
ManagedDisk: &compute.SubResourceArgs{
Id: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk"),
},
OsState: compute.OperatingSystemStateTypesGeneralized,
OsType: compute.OperatingSystemTypesLinux,
},
ZoneResilient: pulumi.Bool(true),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var image = new AzureNative.Compute.Image("image", new()
{
ImageName = "myImage",
Location = "West US",
ResourceGroupName = "myResourceGroup",
StorageProfile = new AzureNative.Compute.Inputs.ImageStorageProfileArgs
{
OsDisk = new AzureNative.Compute.Inputs.ImageOSDiskArgs
{
ManagedDisk = new AzureNative.Compute.Inputs.SubResourceArgs
{
Id = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk",
},
OsState = AzureNative.Compute.OperatingSystemStateTypes.Generalized,
OsType = AzureNative.Compute.OperatingSystemTypes.Linux,
},
ZoneResilient = true,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Image;
import com.pulumi.azurenative.compute.ImageArgs;
import com.pulumi.azurenative.compute.inputs.ImageStorageProfileArgs;
import com.pulumi.azurenative.compute.inputs.ImageOSDiskArgs;
import com.pulumi.azurenative.compute.inputs.SubResourceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var image = new Image("image", ImageArgs.builder()
.imageName("myImage")
.location("West US")
.resourceGroupName("myResourceGroup")
.storageProfile(ImageStorageProfileArgs.builder()
.osDisk(ImageOSDiskArgs.builder()
.managedDisk(SubResourceArgs.builder()
.id("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk")
.build())
.osState("Generalized")
.osType("Linux")
.build())
.zoneResilient(true)
.build())
.build());
}
}
resources:
image:
type: azure-native:compute:Image
properties:
imageName: myImage
location: West US
resourceGroupName: myResourceGroup
storageProfile:
osDisk:
managedDisk:
id: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk
osState: Generalized
osType: Linux
zoneResilient: true
The managedDisk property references an existing disk by ID. This approach is faster than blob-based images because the disk is already in Azure’s managed storage. The disk must contain a generalized OS; specialized disks retain machine-specific configuration and won’t work for multi-VM deployments.
Include data disks in an image
Applications often require both OS and data disks. Images can include multiple disks, allowing you to deploy VMs with pre-configured data volumes.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const image = new azure_native.compute.Image("image", {
imageName: "myImage",
location: "West US",
resourceGroupName: "myResourceGroup",
storageProfile: {
dataDisks: [{
lun: 1,
managedDisk: {
id: "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2",
},
}],
osDisk: {
managedDisk: {
id: "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk",
},
osState: azure_native.compute.OperatingSystemStateTypes.Generalized,
osType: azure_native.compute.OperatingSystemTypes.Linux,
},
zoneResilient: false,
},
});
import pulumi
import pulumi_azure_native as azure_native
image = azure_native.compute.Image("image",
image_name="myImage",
location="West US",
resource_group_name="myResourceGroup",
storage_profile={
"data_disks": [{
"lun": 1,
"managed_disk": {
"id": "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2",
},
}],
"os_disk": {
"managed_disk": {
"id": "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk",
},
"os_state": azure_native.compute.OperatingSystemStateTypes.GENERALIZED,
"os_type": azure_native.compute.OperatingSystemTypes.LINUX,
},
"zone_resilient": False,
})
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewImage(ctx, "image", &compute.ImageArgs{
ImageName: pulumi.String("myImage"),
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
StorageProfile: &compute.ImageStorageProfileArgs{
DataDisks: compute.ImageDataDiskArray{
&compute.ImageDataDiskArgs{
Lun: pulumi.Int(1),
ManagedDisk: &compute.SubResourceArgs{
Id: pulumi.String("subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2"),
},
},
},
OsDisk: &compute.ImageOSDiskArgs{
ManagedDisk: &compute.SubResourceArgs{
Id: pulumi.String("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk"),
},
OsState: compute.OperatingSystemStateTypesGeneralized,
OsType: compute.OperatingSystemTypesLinux,
},
ZoneResilient: pulumi.Bool(false),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var image = new AzureNative.Compute.Image("image", new()
{
ImageName = "myImage",
Location = "West US",
ResourceGroupName = "myResourceGroup",
StorageProfile = new AzureNative.Compute.Inputs.ImageStorageProfileArgs
{
DataDisks = new[]
{
new AzureNative.Compute.Inputs.ImageDataDiskArgs
{
Lun = 1,
ManagedDisk = new AzureNative.Compute.Inputs.SubResourceArgs
{
Id = "subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2",
},
},
},
OsDisk = new AzureNative.Compute.Inputs.ImageOSDiskArgs
{
ManagedDisk = new AzureNative.Compute.Inputs.SubResourceArgs
{
Id = "subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk",
},
OsState = AzureNative.Compute.OperatingSystemStateTypes.Generalized,
OsType = AzureNative.Compute.OperatingSystemTypes.Linux,
},
ZoneResilient = false,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Image;
import com.pulumi.azurenative.compute.ImageArgs;
import com.pulumi.azurenative.compute.inputs.ImageStorageProfileArgs;
import com.pulumi.azurenative.compute.inputs.ImageOSDiskArgs;
import com.pulumi.azurenative.compute.inputs.SubResourceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var image = new Image("image", ImageArgs.builder()
.imageName("myImage")
.location("West US")
.resourceGroupName("myResourceGroup")
.storageProfile(ImageStorageProfileArgs.builder()
.dataDisks(ImageDataDiskArgs.builder()
.lun(1)
.managedDisk(SubResourceArgs.builder()
.id("subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2")
.build())
.build())
.osDisk(ImageOSDiskArgs.builder()
.managedDisk(SubResourceArgs.builder()
.id("subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk")
.build())
.osState("Generalized")
.osType("Linux")
.build())
.zoneResilient(false)
.build())
.build());
}
}
resources:
image:
type: azure-native:compute:Image
properties:
imageName: myImage
location: West US
resourceGroupName: myResourceGroup
storageProfile:
dataDisks:
- lun: 1
managedDisk:
id: subscriptions/{subscriptionId}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk2
osDisk:
managedDisk:
id: subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk
osState: Generalized
osType: Linux
zoneResilient: false
The dataDisks array adds additional volumes to the image. Each data disk requires a lun (Logical Unit Number) that identifies its attachment point. When you deploy a VM from this image, both OS and data disks are created automatically, preserving your application’s storage layout.
Encrypt an image with DiskEncryptionSet
Compliance requirements often mandate encryption at rest using customer-managed keys. DiskEncryptionSet allows you to encrypt images with keys from Azure Key Vault.
import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";
const image = new azure_native.compute.Image("image", {
imageName: "myImage",
location: "West US",
resourceGroupName: "myResourceGroup",
storageProfile: {
osDisk: {
blobUri: "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
diskEncryptionSet: {
id: "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}",
},
osState: azure_native.compute.OperatingSystemStateTypes.Generalized,
osType: azure_native.compute.OperatingSystemTypes.Linux,
},
},
});
import pulumi
import pulumi_azure_native as azure_native
image = azure_native.compute.Image("image",
image_name="myImage",
location="West US",
resource_group_name="myResourceGroup",
storage_profile={
"os_disk": {
"blob_uri": "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
"disk_encryption_set": {
"id": "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}",
},
"os_state": azure_native.compute.OperatingSystemStateTypes.GENERALIZED,
"os_type": azure_native.compute.OperatingSystemTypes.LINUX,
},
})
package main
import (
compute "github.com/pulumi/pulumi-azure-native-sdk/compute/v3"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := compute.NewImage(ctx, "image", &compute.ImageArgs{
ImageName: pulumi.String("myImage"),
Location: pulumi.String("West US"),
ResourceGroupName: pulumi.String("myResourceGroup"),
StorageProfile: &compute.ImageStorageProfileArgs{
OsDisk: &compute.ImageOSDiskArgs{
BlobUri: pulumi.String("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd"),
DiskEncryptionSet: &compute.DiskEncryptionSetParametersArgs{
Id: pulumi.String("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}"),
},
OsState: compute.OperatingSystemStateTypesGeneralized,
OsType: compute.OperatingSystemTypesLinux,
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using AzureNative = Pulumi.AzureNative;
return await Deployment.RunAsync(() =>
{
var image = new AzureNative.Compute.Image("image", new()
{
ImageName = "myImage",
Location = "West US",
ResourceGroupName = "myResourceGroup",
StorageProfile = new AzureNative.Compute.Inputs.ImageStorageProfileArgs
{
OsDisk = new AzureNative.Compute.Inputs.ImageOSDiskArgs
{
BlobUri = "https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd",
DiskEncryptionSet = new AzureNative.Compute.Inputs.DiskEncryptionSetParametersArgs
{
Id = "/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}",
},
OsState = AzureNative.Compute.OperatingSystemStateTypes.Generalized,
OsType = AzureNative.Compute.OperatingSystemTypes.Linux,
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.compute.Image;
import com.pulumi.azurenative.compute.ImageArgs;
import com.pulumi.azurenative.compute.inputs.ImageStorageProfileArgs;
import com.pulumi.azurenative.compute.inputs.ImageOSDiskArgs;
import com.pulumi.azurenative.compute.inputs.DiskEncryptionSetParametersArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var image = new Image("image", ImageArgs.builder()
.imageName("myImage")
.location("West US")
.resourceGroupName("myResourceGroup")
.storageProfile(ImageStorageProfileArgs.builder()
.osDisk(ImageOSDiskArgs.builder()
.blobUri("https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd")
.diskEncryptionSet(DiskEncryptionSetParametersArgs.builder()
.id("/subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}")
.build())
.osState("Generalized")
.osType("Linux")
.build())
.build())
.build());
}
}
resources:
image:
type: azure-native:compute:Image
properties:
imageName: myImage
location: West US
resourceGroupName: myResourceGroup
storageProfile:
osDisk:
blobUri: https://mystorageaccount.blob.core.windows.net/osimages/osimage.vhd
diskEncryptionSet:
id: /subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Compute/diskEncryptionSets/{existing-diskEncryptionSet-name}
osState: Generalized
osType: Linux
The diskEncryptionSet property references a DiskEncryptionSet resource that wraps your Key Vault key. When VMs are deployed from this image, their disks inherit the encryption configuration. The DiskEncryptionSet must exist before image creation and requires permissions to access your Key Vault.
Beyond these examples
These snippets focus on specific image-level features: image sources (VMs, blobs, managed disks, snapshots), multi-disk images with data volumes, and customer-managed encryption with DiskEncryptionSet. They’re intentionally minimal rather than full VM deployment workflows.
The examples may reference pre-existing infrastructure such as VMs in generalized state, VHD blobs in storage accounts, managed disks and snapshots, and DiskEncryptionSets with Key Vault access. They focus on configuring the image rather than provisioning the source resources.
To keep things focused, common image patterns are omitted, including:
- HyperV generation specification (hyperVGeneration)
- Extended location for edge deployments
- Resource tagging for organization
- Zone-resilient storage configuration details
These omissions are intentional: the goal is to illustrate how each image source is wired, not provide drop-in VM templates. See the Image resource reference for all available configuration options.
Let's create Azure VM Images
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Image Sources & Creation
You can create images from four sources:
- Blob VHD - Use
storageProfile.osDisk.blobUri - Managed disk - Use
storageProfile.osDisk.managedDisk - Snapshot - Use
storageProfile.osDisk.snapshot - Existing VM - Use
sourceVirtualMachine.id
osState set to Generalized, indicating the source VM has been generalized before image creation.Encryption & Security
storageProfile.osDisk.diskEncryptionSet.id to reference an existing DiskEncryptionSet resource in your subscription.Configuration & Requirements
hyperVGeneration if it cannot be automatically deduced from the source.location, imageName, and resourceGroupName properties are immutable and cannot be modified after creation.Advanced Features
storageProfile.zoneResilient to true enables zone redundancy, making the image available across availability zones in the region.storageProfile.dataDisks with a lun number and disk source (blobUri, managedDisk, or snapshot).