Deploy Azure Container Instances

The azure-native:containerinstance:ContainerGroup resource, part of the Pulumi Azure Native provider, defines an Azure Container Instances container group: one or more containers that share lifecycle, networking, and storage. This guide focuses on three capabilities: confidential computing with hardware isolation, virtual kubelet extensions for Kubernetes integration, and spot instance pricing.

Container groups run in Azure resource groups and may reference VNet subnets for private networking or container registries for image access. The examples are intentionally small. Combine them with your own networking, storage, and registry configuration.

Deploy confidential containers with hardware-based isolation

Applications handling sensitive data often require hardware-based isolation to protect workloads from the underlying infrastructure.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const containerGroup = new azure_native.containerinstance.ContainerGroup("containerGroup", {
    confidentialComputeProperties: {
        ccePolicy: "eyJhbGxvd19hbGwiOiB0cnVlLCAiY29udGFpbmVycyI6IHsibGVuZ3RoIjogMCwgImVsZW1lbnRzIjogbnVsbH19",
    },
    containerGroupName: "demo1",
    containers: [{
        command: [],
        environmentVariables: [],
        image: "confiimage",
        name: "accdemo",
        ports: [{
            port: 8000,
        }],
        resources: {
            requests: {
                cpu: 1,
                memoryInGB: 1.5,
            },
        },
        securityContext: {
            capabilities: {
                add: ["CAP_NET_ADMIN"],
            },
            privileged: false,
        },
    }],
    imageRegistryCredentials: [],
    ipAddress: {
        ports: [{
            port: 8000,
            protocol: azure_native.containerinstance.ContainerGroupNetworkProtocol.TCP,
        }],
        type: azure_native.containerinstance.ContainerGroupIpAddressType.Public,
    },
    location: "westeurope",
    osType: azure_native.containerinstance.OperatingSystemTypes.Linux,
    resourceGroupName: "demo",
    sku: azure_native.containerinstance.ContainerGroupSku.Confidential,
});
import pulumi
import pulumi_azure_native as azure_native

container_group = azure_native.containerinstance.ContainerGroup("containerGroup",
    confidential_compute_properties={
        "cce_policy": "eyJhbGxvd19hbGwiOiB0cnVlLCAiY29udGFpbmVycyI6IHsibGVuZ3RoIjogMCwgImVsZW1lbnRzIjogbnVsbH19",
    },
    container_group_name="demo1",
    containers=[{
        "command": [],
        "environment_variables": [],
        "image": "confiimage",
        "name": "accdemo",
        "ports": [{
            "port": 8000,
        }],
        "resources": {
            "requests": {
                "cpu": 1,
                "memory_in_gb": 1.5,
            },
        },
        "security_context": {
            "capabilities": {
                "add": ["CAP_NET_ADMIN"],
            },
            "privileged": False,
        },
    }],
    image_registry_credentials=[],
    ip_address={
        "ports": [{
            "port": 8000,
            "protocol": azure_native.containerinstance.ContainerGroupNetworkProtocol.TCP,
        }],
        "type": azure_native.containerinstance.ContainerGroupIpAddressType.PUBLIC,
    },
    location="westeurope",
    os_type=azure_native.containerinstance.OperatingSystemTypes.LINUX,
    resource_group_name="demo",
    sku=azure_native.containerinstance.ContainerGroupSku.CONFIDENTIAL)
package main

import (
	containerinstance "github.com/pulumi/pulumi-azure-native-sdk/containerinstance/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := containerinstance.NewContainerGroup(ctx, "containerGroup", &containerinstance.ContainerGroupArgs{
			ConfidentialComputeProperties: &containerinstance.ConfidentialComputePropertiesArgs{
				CcePolicy: pulumi.String("eyJhbGxvd19hbGwiOiB0cnVlLCAiY29udGFpbmVycyI6IHsibGVuZ3RoIjogMCwgImVsZW1lbnRzIjogbnVsbH19"),
			},
			ContainerGroupName: pulumi.String("demo1"),
			Containers: containerinstance.ContainerArray{
				&containerinstance.ContainerArgs{
					Command:              pulumi.StringArray{},
					EnvironmentVariables: containerinstance.EnvironmentVariableArray{},
					Image:                pulumi.String("confiimage"),
					Name:                 pulumi.String("accdemo"),
					Ports: containerinstance.ContainerPortArray{
						&containerinstance.ContainerPortArgs{
							Port: pulumi.Int(8000),
						},
					},
					Resources: &containerinstance.ResourceRequirementsArgs{
						Requests: &containerinstance.ResourceRequestsArgs{
							Cpu:        pulumi.Float64(1),
							MemoryInGB: pulumi.Float64(1.5),
						},
					},
					SecurityContext: &containerinstance.SecurityContextDefinitionArgs{
						Capabilities: &containerinstance.SecurityContextCapabilitiesDefinitionArgs{
							Add: pulumi.StringArray{
								pulumi.String("CAP_NET_ADMIN"),
							},
						},
						Privileged: pulumi.Bool(false),
					},
				},
			},
			ImageRegistryCredentials: containerinstance.ImageRegistryCredentialArray{},
			IpAddress: &containerinstance.IpAddressArgs{
				Ports: containerinstance.PortArray{
					&containerinstance.PortArgs{
						Port:     pulumi.Int(8000),
						Protocol: pulumi.String(containerinstance.ContainerGroupNetworkProtocolTCP),
					},
				},
				Type: pulumi.String(containerinstance.ContainerGroupIpAddressTypePublic),
			},
			Location:          pulumi.String("westeurope"),
			OsType:            pulumi.String(containerinstance.OperatingSystemTypesLinux),
			ResourceGroupName: pulumi.String("demo"),
			Sku:               pulumi.String(containerinstance.ContainerGroupSkuConfidential),
		})
		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 containerGroup = new AzureNative.ContainerInstance.ContainerGroup("containerGroup", new()
    {
        ConfidentialComputeProperties = new AzureNative.ContainerInstance.Inputs.ConfidentialComputePropertiesArgs
        {
            CcePolicy = "eyJhbGxvd19hbGwiOiB0cnVlLCAiY29udGFpbmVycyI6IHsibGVuZ3RoIjogMCwgImVsZW1lbnRzIjogbnVsbH19",
        },
        ContainerGroupName = "demo1",
        Containers = new[]
        {
            new AzureNative.ContainerInstance.Inputs.ContainerArgs
            {
                Command = new() { },
                EnvironmentVariables = new() { },
                Image = "confiimage",
                Name = "accdemo",
                Ports = new[]
                {
                    new AzureNative.ContainerInstance.Inputs.ContainerPortArgs
                    {
                        Port = 8000,
                    },
                },
                Resources = new AzureNative.ContainerInstance.Inputs.ResourceRequirementsArgs
                {
                    Requests = new AzureNative.ContainerInstance.Inputs.ResourceRequestsArgs
                    {
                        Cpu = 1,
                        MemoryInGB = 1.5,
                    },
                },
                SecurityContext = new AzureNative.ContainerInstance.Inputs.SecurityContextDefinitionArgs
                {
                    Capabilities = new AzureNative.ContainerInstance.Inputs.SecurityContextCapabilitiesDefinitionArgs
                    {
                        Add = new[]
                        {
                            "CAP_NET_ADMIN",
                        },
                    },
                    Privileged = false,
                },
            },
        },
        ImageRegistryCredentials = new[] {},
        IpAddress = new AzureNative.ContainerInstance.Inputs.IpAddressArgs
        {
            Ports = new[]
            {
                new AzureNative.ContainerInstance.Inputs.PortArgs
                {
                    Port = 8000,
                    Protocol = AzureNative.ContainerInstance.ContainerGroupNetworkProtocol.TCP,
                },
            },
            Type = AzureNative.ContainerInstance.ContainerGroupIpAddressType.Public,
        },
        Location = "westeurope",
        OsType = AzureNative.ContainerInstance.OperatingSystemTypes.Linux,
        ResourceGroupName = "demo",
        Sku = AzureNative.ContainerInstance.ContainerGroupSku.Confidential,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.containerinstance.ContainerGroup;
import com.pulumi.azurenative.containerinstance.ContainerGroupArgs;
import com.pulumi.azurenative.containerinstance.inputs.ConfidentialComputePropertiesArgs;
import com.pulumi.azurenative.containerinstance.inputs.ContainerArgs;
import com.pulumi.azurenative.containerinstance.inputs.ResourceRequirementsArgs;
import com.pulumi.azurenative.containerinstance.inputs.ResourceRequestsArgs;
import com.pulumi.azurenative.containerinstance.inputs.SecurityContextDefinitionArgs;
import com.pulumi.azurenative.containerinstance.inputs.SecurityContextCapabilitiesDefinitionArgs;
import com.pulumi.azurenative.containerinstance.inputs.IpAddressArgs;
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 containerGroup = new ContainerGroup("containerGroup", ContainerGroupArgs.builder()
            .confidentialComputeProperties(ConfidentialComputePropertiesArgs.builder()
                .ccePolicy("eyJhbGxvd19hbGwiOiB0cnVlLCAiY29udGFpbmVycyI6IHsibGVuZ3RoIjogMCwgImVsZW1lbnRzIjogbnVsbH19")
                .build())
            .containerGroupName("demo1")
            .containers(ContainerArgs.builder()
                .command()
                .environmentVariables()
                .image("confiimage")
                .name("accdemo")
                .ports(ContainerPortArgs.builder()
                    .port(8000)
                    .build())
                .resources(ResourceRequirementsArgs.builder()
                    .requests(ResourceRequestsArgs.builder()
                        .cpu(1.0)
                        .memoryInGB(1.5)
                        .build())
                    .build())
                .securityContext(SecurityContextDefinitionArgs.builder()
                    .capabilities(SecurityContextCapabilitiesDefinitionArgs.builder()
                        .add("CAP_NET_ADMIN")
                        .build())
                    .privileged(false)
                    .build())
                .build())
            .imageRegistryCredentials()
            .ipAddress(IpAddressArgs.builder()
                .ports(PortArgs.builder()
                    .port(8000)
                    .protocol("TCP")
                    .build())
                .type("Public")
                .build())
            .location("westeurope")
            .osType("Linux")
            .resourceGroupName("demo")
            .sku("Confidential")
            .build());

    }
}
resources:
  containerGroup:
    type: azure-native:containerinstance:ContainerGroup
    properties:
      confidentialComputeProperties:
        ccePolicy: eyJhbGxvd19hbGwiOiB0cnVlLCAiY29udGFpbmVycyI6IHsibGVuZ3RoIjogMCwgImVsZW1lbnRzIjogbnVsbH19
      containerGroupName: demo1
      containers:
        - command: []
          environmentVariables: []
          image: confiimage
          name: accdemo
          ports:
            - port: 8000
          resources:
            requests:
              cpu: 1
              memoryInGB: 1.5
          securityContext:
            capabilities:
              add:
                - CAP_NET_ADMIN
            privileged: false
      imageRegistryCredentials: []
      ipAddress:
        ports:
          - port: 8000
            protocol: TCP
        type: Public
      location: westeurope
      osType: Linux
      resourceGroupName: demo
      sku: Confidential

The sku property set to “Confidential” enables AMD SEV-SNP hardware isolation. The confidentialComputeProperties block contains a ccePolicy (Confidential Container Enforcement policy) that defines attestation rules. The securityContext allows you to grant specific Linux capabilities while maintaining isolation boundaries.

Integrate with virtual kubelet extensions

Teams running Kubernetes workloads on Azure Container Instances can add capabilities through extensions.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const containerGroup = new azure_native.containerinstance.ContainerGroup("containerGroup", {
    containerGroupName: "demo1",
    containers: [{
        command: [],
        environmentVariables: [],
        image: "nginx",
        name: "demo1",
        ports: [{
            port: 80,
        }],
        resources: {
            requests: {
                cpu: 1,
                memoryInGB: 1.5,
            },
        },
    }],
    extensions: [
        {
            extensionType: "kube-proxy",
            name: "kube-proxy",
            protectedSettings: {
                kubeConfig: "<kubeconfig encoded string>",
            },
            settings: {
                clusterCidr: "10.240.0.0/16",
                kubeVersion: "v1.9.10",
            },
            version: "1.0",
        },
        {
            extensionType: "realtime-metrics",
            name: "vk-realtime-metrics",
            version: "1.0",
        },
    ],
    imageRegistryCredentials: [],
    ipAddress: {
        ports: [{
            port: 80,
            protocol: azure_native.containerinstance.ContainerGroupNetworkProtocol.TCP,
        }],
        type: azure_native.containerinstance.ContainerGroupIpAddressType.Private,
    },
    location: "eastus2",
    osType: azure_native.containerinstance.OperatingSystemTypes.Linux,
    resourceGroupName: "demo",
    subnetIds: [{
        id: "/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-rg-vnet/subnets/test-subnet",
    }],
});
import pulumi
import pulumi_azure_native as azure_native

container_group = azure_native.containerinstance.ContainerGroup("containerGroup",
    container_group_name="demo1",
    containers=[{
        "command": [],
        "environment_variables": [],
        "image": "nginx",
        "name": "demo1",
        "ports": [{
            "port": 80,
        }],
        "resources": {
            "requests": {
                "cpu": 1,
                "memory_in_gb": 1.5,
            },
        },
    }],
    extensions=[
        {
            "extension_type": "kube-proxy",
            "name": "kube-proxy",
            "protected_settings": {
                "kubeConfig": "<kubeconfig encoded string>",
            },
            "settings": {
                "clusterCidr": "10.240.0.0/16",
                "kubeVersion": "v1.9.10",
            },
            "version": "1.0",
        },
        {
            "extension_type": "realtime-metrics",
            "name": "vk-realtime-metrics",
            "version": "1.0",
        },
    ],
    image_registry_credentials=[],
    ip_address={
        "ports": [{
            "port": 80,
            "protocol": azure_native.containerinstance.ContainerGroupNetworkProtocol.TCP,
        }],
        "type": azure_native.containerinstance.ContainerGroupIpAddressType.PRIVATE,
    },
    location="eastus2",
    os_type=azure_native.containerinstance.OperatingSystemTypes.LINUX,
    resource_group_name="demo",
    subnet_ids=[{
        "id": "/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-rg-vnet/subnets/test-subnet",
    }])
package main

import (
	containerinstance "github.com/pulumi/pulumi-azure-native-sdk/containerinstance/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := containerinstance.NewContainerGroup(ctx, "containerGroup", &containerinstance.ContainerGroupArgs{
			ContainerGroupName: pulumi.String("demo1"),
			Containers: containerinstance.ContainerArray{
				&containerinstance.ContainerArgs{
					Command:              pulumi.StringArray{},
					EnvironmentVariables: containerinstance.EnvironmentVariableArray{},
					Image:                pulumi.String("nginx"),
					Name:                 pulumi.String("demo1"),
					Ports: containerinstance.ContainerPortArray{
						&containerinstance.ContainerPortArgs{
							Port: pulumi.Int(80),
						},
					},
					Resources: &containerinstance.ResourceRequirementsArgs{
						Requests: &containerinstance.ResourceRequestsArgs{
							Cpu:        pulumi.Float64(1),
							MemoryInGB: pulumi.Float64(1.5),
						},
					},
				},
			},
			Extensions: containerinstance.DeploymentExtensionSpecArray{
				&containerinstance.DeploymentExtensionSpecArgs{
					ExtensionType: pulumi.String("kube-proxy"),
					Name:          pulumi.String("kube-proxy"),
					ProtectedSettings: pulumi.Any(map[string]interface{}{
						"kubeConfig": "<kubeconfig encoded string>",
					}),
					Settings: pulumi.Any(map[string]interface{}{
						"clusterCidr": "10.240.0.0/16",
						"kubeVersion": "v1.9.10",
					}),
					Version: pulumi.String("1.0"),
				},
				&containerinstance.DeploymentExtensionSpecArgs{
					ExtensionType: pulumi.String("realtime-metrics"),
					Name:          pulumi.String("vk-realtime-metrics"),
					Version:       pulumi.String("1.0"),
				},
			},
			ImageRegistryCredentials: containerinstance.ImageRegistryCredentialArray{},
			IpAddress: &containerinstance.IpAddressArgs{
				Ports: containerinstance.PortArray{
					&containerinstance.PortArgs{
						Port:     pulumi.Int(80),
						Protocol: pulumi.String(containerinstance.ContainerGroupNetworkProtocolTCP),
					},
				},
				Type: pulumi.String(containerinstance.ContainerGroupIpAddressTypePrivate),
			},
			Location:          pulumi.String("eastus2"),
			OsType:            pulumi.String(containerinstance.OperatingSystemTypesLinux),
			ResourceGroupName: pulumi.String("demo"),
			SubnetIds: containerinstance.ContainerGroupSubnetIdArray{
				&containerinstance.ContainerGroupSubnetIdArgs{
					Id: pulumi.String("/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-rg-vnet/subnets/test-subnet"),
				},
			},
		})
		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 containerGroup = new AzureNative.ContainerInstance.ContainerGroup("containerGroup", new()
    {
        ContainerGroupName = "demo1",
        Containers = new[]
        {
            new AzureNative.ContainerInstance.Inputs.ContainerArgs
            {
                Command = new() { },
                EnvironmentVariables = new() { },
                Image = "nginx",
                Name = "demo1",
                Ports = new[]
                {
                    new AzureNative.ContainerInstance.Inputs.ContainerPortArgs
                    {
                        Port = 80,
                    },
                },
                Resources = new AzureNative.ContainerInstance.Inputs.ResourceRequirementsArgs
                {
                    Requests = new AzureNative.ContainerInstance.Inputs.ResourceRequestsArgs
                    {
                        Cpu = 1,
                        MemoryInGB = 1.5,
                    },
                },
            },
        },
        Extensions = new[]
        {
            new AzureNative.ContainerInstance.Inputs.DeploymentExtensionSpecArgs
            {
                ExtensionType = "kube-proxy",
                Name = "kube-proxy",
                ProtectedSettings = new Dictionary<string, object?>
                {
                    ["kubeConfig"] = "<kubeconfig encoded string>",
                },
                Settings = new Dictionary<string, object?>
                {
                    ["clusterCidr"] = "10.240.0.0/16",
                    ["kubeVersion"] = "v1.9.10",
                },
                Version = "1.0",
            },
            new AzureNative.ContainerInstance.Inputs.DeploymentExtensionSpecArgs
            {
                ExtensionType = "realtime-metrics",
                Name = "vk-realtime-metrics",
                Version = "1.0",
            },
        },
        ImageRegistryCredentials = new[] {},
        IpAddress = new AzureNative.ContainerInstance.Inputs.IpAddressArgs
        {
            Ports = new[]
            {
                new AzureNative.ContainerInstance.Inputs.PortArgs
                {
                    Port = 80,
                    Protocol = AzureNative.ContainerInstance.ContainerGroupNetworkProtocol.TCP,
                },
            },
            Type = AzureNative.ContainerInstance.ContainerGroupIpAddressType.Private,
        },
        Location = "eastus2",
        OsType = AzureNative.ContainerInstance.OperatingSystemTypes.Linux,
        ResourceGroupName = "demo",
        SubnetIds = new[]
        {
            new AzureNative.ContainerInstance.Inputs.ContainerGroupSubnetIdArgs
            {
                Id = "/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-rg-vnet/subnets/test-subnet",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.containerinstance.ContainerGroup;
import com.pulumi.azurenative.containerinstance.ContainerGroupArgs;
import com.pulumi.azurenative.containerinstance.inputs.ContainerArgs;
import com.pulumi.azurenative.containerinstance.inputs.ResourceRequirementsArgs;
import com.pulumi.azurenative.containerinstance.inputs.ResourceRequestsArgs;
import com.pulumi.azurenative.containerinstance.inputs.DeploymentExtensionSpecArgs;
import com.pulumi.azurenative.containerinstance.inputs.IpAddressArgs;
import com.pulumi.azurenative.containerinstance.inputs.ContainerGroupSubnetIdArgs;
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 containerGroup = new ContainerGroup("containerGroup", ContainerGroupArgs.builder()
            .containerGroupName("demo1")
            .containers(ContainerArgs.builder()
                .command()
                .environmentVariables()
                .image("nginx")
                .name("demo1")
                .ports(ContainerPortArgs.builder()
                    .port(80)
                    .build())
                .resources(ResourceRequirementsArgs.builder()
                    .requests(ResourceRequestsArgs.builder()
                        .cpu(1.0)
                        .memoryInGB(1.5)
                        .build())
                    .build())
                .build())
            .extensions(            
                DeploymentExtensionSpecArgs.builder()
                    .extensionType("kube-proxy")
                    .name("kube-proxy")
                    .protectedSettings(Map.of("kubeConfig", "<kubeconfig encoded string>"))
                    .settings(Map.ofEntries(
                        Map.entry("clusterCidr", "10.240.0.0/16"),
                        Map.entry("kubeVersion", "v1.9.10")
                    ))
                    .version("1.0")
                    .build(),
                DeploymentExtensionSpecArgs.builder()
                    .extensionType("realtime-metrics")
                    .name("vk-realtime-metrics")
                    .version("1.0")
                    .build())
            .imageRegistryCredentials()
            .ipAddress(IpAddressArgs.builder()
                .ports(PortArgs.builder()
                    .port(80)
                    .protocol("TCP")
                    .build())
                .type("Private")
                .build())
            .location("eastus2")
            .osType("Linux")
            .resourceGroupName("demo")
            .subnetIds(ContainerGroupSubnetIdArgs.builder()
                .id("/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-rg-vnet/subnets/test-subnet")
                .build())
            .build());

    }
}
resources:
  containerGroup:
    type: azure-native:containerinstance:ContainerGroup
    properties:
      containerGroupName: demo1
      containers:
        - command: []
          environmentVariables: []
          image: nginx
          name: demo1
          ports:
            - port: 80
          resources:
            requests:
              cpu: 1
              memoryInGB: 1.5
      extensions:
        - extensionType: kube-proxy
          name: kube-proxy
          protectedSettings:
            kubeConfig: <kubeconfig encoded string>
          settings:
            clusterCidr: 10.240.0.0/16
            kubeVersion: v1.9.10
          version: '1.0'
        - extensionType: realtime-metrics
          name: vk-realtime-metrics
          version: '1.0'
      imageRegistryCredentials: []
      ipAddress:
        ports:
          - port: 80
            protocol: TCP
        type: Private
      location: eastus2
      osType: Linux
      resourceGroupName: demo
      subnetIds:
        - id: /subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks/test-rg-vnet/subnets/test-subnet

The extensions array adds functionality to the container group. The kube-proxy extension enables Kubernetes networking, requiring a kubeconfig in protectedSettings and cluster configuration in settings. The realtime-metrics extension adds monitoring. The subnetIds property places the group in a VNet subnet for private networking.

Request spot instances for cost-optimized workloads

Batch jobs and fault-tolerant workloads can reduce costs by running on spot instances.

import * as pulumi from "@pulumi/pulumi";
import * as azure_native from "@pulumi/azure-native";

const containerGroup = new azure_native.containerinstance.ContainerGroup("containerGroup", {
    containerGroupName: "demo1",
    containers: [{
        command: [
            "/bin/sh",
            "-c",
            "sleep 10",
        ],
        image: "alpine:latest",
        name: "test-container-001",
        resources: {
            requests: {
                cpu: 1,
                memoryInGB: 1,
            },
        },
    }],
    location: "eastus",
    osType: azure_native.containerinstance.OperatingSystemTypes.Linux,
    priority: azure_native.containerinstance.ContainerGroupPriority.Spot,
    resourceGroupName: "demo",
    restartPolicy: azure_native.containerinstance.ContainerGroupRestartPolicy.Never,
    sku: azure_native.containerinstance.ContainerGroupSku.Standard,
});
import pulumi
import pulumi_azure_native as azure_native

container_group = azure_native.containerinstance.ContainerGroup("containerGroup",
    container_group_name="demo1",
    containers=[{
        "command": [
            "/bin/sh",
            "-c",
            "sleep 10",
        ],
        "image": "alpine:latest",
        "name": "test-container-001",
        "resources": {
            "requests": {
                "cpu": 1,
                "memory_in_gb": 1,
            },
        },
    }],
    location="eastus",
    os_type=azure_native.containerinstance.OperatingSystemTypes.LINUX,
    priority=azure_native.containerinstance.ContainerGroupPriority.SPOT,
    resource_group_name="demo",
    restart_policy=azure_native.containerinstance.ContainerGroupRestartPolicy.NEVER,
    sku=azure_native.containerinstance.ContainerGroupSku.STANDARD)
package main

import (
	containerinstance "github.com/pulumi/pulumi-azure-native-sdk/containerinstance/v3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := containerinstance.NewContainerGroup(ctx, "containerGroup", &containerinstance.ContainerGroupArgs{
			ContainerGroupName: pulumi.String("demo1"),
			Containers: containerinstance.ContainerArray{
				&containerinstance.ContainerArgs{
					Command: pulumi.StringArray{
						pulumi.String("/bin/sh"),
						pulumi.String("-c"),
						pulumi.String("sleep 10"),
					},
					Image: pulumi.String("alpine:latest"),
					Name:  pulumi.String("test-container-001"),
					Resources: &containerinstance.ResourceRequirementsArgs{
						Requests: &containerinstance.ResourceRequestsArgs{
							Cpu:        pulumi.Float64(1),
							MemoryInGB: pulumi.Float64(1),
						},
					},
				},
			},
			Location:          pulumi.String("eastus"),
			OsType:            pulumi.String(containerinstance.OperatingSystemTypesLinux),
			Priority:          pulumi.String(containerinstance.ContainerGroupPrioritySpot),
			ResourceGroupName: pulumi.String("demo"),
			RestartPolicy:     pulumi.String(containerinstance.ContainerGroupRestartPolicyNever),
			Sku:               pulumi.String(containerinstance.ContainerGroupSkuStandard),
		})
		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 containerGroup = new AzureNative.ContainerInstance.ContainerGroup("containerGroup", new()
    {
        ContainerGroupName = "demo1",
        Containers = new[]
        {
            new AzureNative.ContainerInstance.Inputs.ContainerArgs
            {
                Command = new[]
                {
                    "/bin/sh",
                    "-c",
                    "sleep 10",
                },
                Image = "alpine:latest",
                Name = "test-container-001",
                Resources = new AzureNative.ContainerInstance.Inputs.ResourceRequirementsArgs
                {
                    Requests = new AzureNative.ContainerInstance.Inputs.ResourceRequestsArgs
                    {
                        Cpu = 1,
                        MemoryInGB = 1,
                    },
                },
            },
        },
        Location = "eastus",
        OsType = AzureNative.ContainerInstance.OperatingSystemTypes.Linux,
        Priority = AzureNative.ContainerInstance.ContainerGroupPriority.Spot,
        ResourceGroupName = "demo",
        RestartPolicy = AzureNative.ContainerInstance.ContainerGroupRestartPolicy.Never,
        Sku = AzureNative.ContainerInstance.ContainerGroupSku.Standard,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.containerinstance.ContainerGroup;
import com.pulumi.azurenative.containerinstance.ContainerGroupArgs;
import com.pulumi.azurenative.containerinstance.inputs.ContainerArgs;
import com.pulumi.azurenative.containerinstance.inputs.ResourceRequirementsArgs;
import com.pulumi.azurenative.containerinstance.inputs.ResourceRequestsArgs;
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 containerGroup = new ContainerGroup("containerGroup", ContainerGroupArgs.builder()
            .containerGroupName("demo1")
            .containers(ContainerArgs.builder()
                .command(                
                    "/bin/sh",
                    "-c",
                    "sleep 10")
                .image("alpine:latest")
                .name("test-container-001")
                .resources(ResourceRequirementsArgs.builder()
                    .requests(ResourceRequestsArgs.builder()
                        .cpu(1.0)
                        .memoryInGB(1.0)
                        .build())
                    .build())
                .build())
            .location("eastus")
            .osType("Linux")
            .priority("Spot")
            .resourceGroupName("demo")
            .restartPolicy("Never")
            .sku("Standard")
            .build());

    }
}
resources:
  containerGroup:
    type: azure-native:containerinstance:ContainerGroup
    properties:
      containerGroupName: demo1
      containers:
        - command:
            - /bin/sh
            - -c
            - sleep 10
          image: alpine:latest
          name: test-container-001
          resources:
            requests:
              cpu: 1
              memoryInGB: 1
      location: eastus
      osType: Linux
      priority: Spot
      resourceGroupName: demo
      restartPolicy: Never
      sku: Standard

The priority property set to “Spot” requests spare Azure capacity at reduced prices. Spot instances may be interrupted when Azure needs the capacity back. The restartPolicy set to “Never” prevents automatic restarts, appropriate for batch jobs that track completion externally.

Beyond these examples

These snippets focus on specific container group features: confidential computing and hardware isolation, virtual kubelet extensions, and spot instance pricing. They’re intentionally minimal rather than full container deployments.

The examples may reference pre-existing infrastructure such as Azure resource groups, VNet subnets for private networking, and container images in accessible registries. They focus on configuring the container group rather than provisioning everything around it.

To keep things focused, common container group patterns are omitted, including:

  • Private registry authentication (imageRegistryCredentials)
  • Volume mounts and persistent storage
  • DNS configuration and custom name resolution
  • Init containers for setup tasks

These omissions are intentional: the goal is to illustrate how each container group feature is wired, not provide drop-in container modules. See the ContainerGroup resource reference for all available configuration options.

Let's deploy Azure Container Instances

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration Basics
What properties can't I change after creating a container group?
The containerGroupName and resourceGroupName are immutable and cannot be changed after creation. You’ll need to recreate the container group to change these values.
What's required to create a container group?
You must specify containers (array with at least one container), and each container needs image, name, and resources.requests (with cpu and memoryInGB). The osType (Linux or Windows) is also required.
What SKUs are available for container groups?
Container groups support two SKUs: Standard (default) and Confidential. The Confidential SKU enables confidential computing features with hardware-based security.
What restart policies can I use?
Three restart policies are available: Always (always restart containers), OnFailure (restart only on failure), and Never (never restart). The policy applies to all containers in the group.
How do I use Spot priority for lower-cost workloads?
Set priority to Spot for interruptible, lower-cost container instances. Combine with restartPolicy: Never for batch workloads that can tolerate interruptions.
Networking & Connectivity
How do I connect my container group to a virtual network?
Configure subnetIds with your subnet resource IDs and set ipAddress.type to Private. The subnet must be delegated to Microsoft.ContainerInstance/containerGroups.
What's the difference between Public and Private IP address types?
Public IP addresses are accessible from the internet, while Private IP addresses require VNet integration via subnetIds and are only accessible within the virtual network.
Advanced Features
How do I create a confidential container group?
Set sku to Confidential and configure confidentialComputeProperties with a ccePolicy (base64-encoded policy string that defines the security policy).
How do I use a standby pool with my container group?
Reference a containerGroupProfile (with id and revision number) and specify a standbyPoolProfile with the standby pool resource ID. This enables faster container startup from pre-warmed instances.
How do I override settings when using a container group profile?
Add a configMap with keyValuePairs to the container definition. This allows you to override specific configuration values from the profile at deployment time.
How do I add extensions like kube-proxy to my container group?
Use the extensions array with objects specifying extensionType (e.g., kube-proxy, realtime-metrics), name, version, and optional settings or protectedSettings for configuration.
Container Security
How do I add Linux capabilities to a container?
Configure securityContext.capabilities.add with an array of capability names (e.g., CAP_NET_ADMIN). Set securityContext.privileged to false unless elevated privileges are required.

Using a different cloud?

Explore containers guides for other cloud providers: