Create Azure Blob Storage Containers

The azure-native:storage:BlobContainer resource, part of the Pulumi Azure Native provider, defines a blob container within an Azure Storage account: its name, encryption settings, and immutability policies. This guide focuses on three capabilities: basic container creation, encryption scope enforcement, and object-level immutability with versioning.

Blob containers belong to storage accounts and resource groups that must already exist. The examples are intentionally small. Combine them with your own storage accounts, encryption scopes, and access policies.

Create a basic blob container

Most deployments start by creating a container within an existing storage account to organize blobs.

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

const blobContainer = new azure_native.storage.BlobContainer("blobContainer", {
    accountName: "sto328",
    containerName: "container6185",
    resourceGroupName: "res3376",
});
import pulumi
import pulumi_azure_native as azure_native

blob_container = azure_native.storage.BlobContainer("blobContainer",
    account_name="sto328",
    container_name="container6185",
    resource_group_name="res3376")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storage.NewBlobContainer(ctx, "blobContainer", &storage.BlobContainerArgs{
			AccountName:       pulumi.String("sto328"),
			ContainerName:     pulumi.String("container6185"),
			ResourceGroupName: pulumi.String("res3376"),
		})
		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 blobContainer = new AzureNative.Storage.BlobContainer("blobContainer", new()
    {
        AccountName = "sto328",
        ContainerName = "container6185",
        ResourceGroupName = "res3376",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.BlobContainer;
import com.pulumi.azurenative.storage.BlobContainerArgs;
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 blobContainer = new BlobContainer("blobContainer", BlobContainerArgs.builder()
            .accountName("sto328")
            .containerName("container6185")
            .resourceGroupName("res3376")
            .build());

    }
}
resources:
  blobContainer:
    type: azure-native:storage:BlobContainer
    properties:
      accountName: sto328
      containerName: container6185
      resourceGroupName: res3376

The accountName references the storage account that will host the container. The containerName must be between 3 and 63 characters, using only lowercase letters, numbers, and dashes. The container acts as a namespace for organizing blobs, similar to a folder in a file system.

Enforce encryption scope for all container writes

Organizations with strict data governance requirements often need to ensure all blobs use a specific encryption scope, preventing users from overriding encryption settings.

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

const blobContainer = new azure_native.storage.BlobContainer("blobContainer", {
    accountName: "sto328",
    containerName: "container6185",
    defaultEncryptionScope: "encryptionscope185",
    denyEncryptionScopeOverride: true,
    resourceGroupName: "res3376",
});
import pulumi
import pulumi_azure_native as azure_native

blob_container = azure_native.storage.BlobContainer("blobContainer",
    account_name="sto328",
    container_name="container6185",
    default_encryption_scope="encryptionscope185",
    deny_encryption_scope_override=True,
    resource_group_name="res3376")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storage.NewBlobContainer(ctx, "blobContainer", &storage.BlobContainerArgs{
			AccountName:                 pulumi.String("sto328"),
			ContainerName:               pulumi.String("container6185"),
			DefaultEncryptionScope:      pulumi.String("encryptionscope185"),
			DenyEncryptionScopeOverride: pulumi.Bool(true),
			ResourceGroupName:           pulumi.String("res3376"),
		})
		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 blobContainer = new AzureNative.Storage.BlobContainer("blobContainer", new()
    {
        AccountName = "sto328",
        ContainerName = "container6185",
        DefaultEncryptionScope = "encryptionscope185",
        DenyEncryptionScopeOverride = true,
        ResourceGroupName = "res3376",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.BlobContainer;
import com.pulumi.azurenative.storage.BlobContainerArgs;
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 blobContainer = new BlobContainer("blobContainer", BlobContainerArgs.builder()
            .accountName("sto328")
            .containerName("container6185")
            .defaultEncryptionScope("encryptionscope185")
            .denyEncryptionScopeOverride(true)
            .resourceGroupName("res3376")
            .build());

    }
}
resources:
  blobContainer:
    type: azure-native:storage:BlobContainer
    properties:
      accountName: sto328
      containerName: container6185
      defaultEncryptionScope: encryptionscope185
      denyEncryptionScopeOverride: true
      resourceGroupName: res3376

The defaultEncryptionScope property specifies which encryption scope the container uses for all writes. When denyEncryptionScopeOverride is set to true, users cannot override this setting at the blob level, ensuring consistent encryption across all container data.

Enable object-level immutability with versioning

Compliance requirements sometimes mandate that data cannot be modified or deleted for a specified retention period.

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

const blobContainer = new azure_native.storage.BlobContainer("blobContainer", {
    accountName: "sto328",
    containerName: "container6185",
    immutableStorageWithVersioning: {
        enabled: true,
    },
    resourceGroupName: "res3376",
});
import pulumi
import pulumi_azure_native as azure_native

blob_container = azure_native.storage.BlobContainer("blobContainer",
    account_name="sto328",
    container_name="container6185",
    immutable_storage_with_versioning={
        "enabled": True,
    },
    resource_group_name="res3376")
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := storage.NewBlobContainer(ctx, "blobContainer", &storage.BlobContainerArgs{
			AccountName:   pulumi.String("sto328"),
			ContainerName: pulumi.String("container6185"),
			ImmutableStorageWithVersioning: &storage.ImmutableStorageWithVersioningArgs{
				Enabled: pulumi.Bool(true),
			},
			ResourceGroupName: pulumi.String("res3376"),
		})
		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 blobContainer = new AzureNative.Storage.BlobContainer("blobContainer", new()
    {
        AccountName = "sto328",
        ContainerName = "container6185",
        ImmutableStorageWithVersioning = new AzureNative.Storage.Inputs.ImmutableStorageWithVersioningArgs
        {
            Enabled = true,
        },
        ResourceGroupName = "res3376",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.azurenative.storage.BlobContainer;
import com.pulumi.azurenative.storage.BlobContainerArgs;
import com.pulumi.azurenative.storage.inputs.ImmutableStorageWithVersioningArgs;
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 blobContainer = new BlobContainer("blobContainer", BlobContainerArgs.builder()
            .accountName("sto328")
            .containerName("container6185")
            .immutableStorageWithVersioning(ImmutableStorageWithVersioningArgs.builder()
                .enabled(true)
                .build())
            .resourceGroupName("res3376")
            .build());

    }
}
resources:
  blobContainer:
    type: azure-native:storage:BlobContainer
    properties:
      accountName: sto328
      containerName: container6185
      immutableStorageWithVersioning:
        enabled: true
      resourceGroupName: res3376

The immutableStorageWithVersioning property enables object-level WORM (Write Once, Read Many) protection. When enabled is set to true, blobs in the container become immutable according to retention policies. This property is immutable itself and can only be set at container creation time; existing containers must undergo a migration process.

Beyond these examples

These snippets focus on specific container-level features: container creation and naming, encryption scope enforcement, and object-level immutability. They’re intentionally minimal rather than full storage solutions.

The examples reference pre-existing infrastructure such as Azure storage accounts, resource groups, and encryption scopes (for the encryption example). They focus on configuring the container rather than provisioning the surrounding storage infrastructure.

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

  • Public access levels (publicAccess)
  • Container metadata (metadata)
  • NFSv3 squash settings (enableNfsV3AllSquash, enableNfsV3RootSquash)
  • Lease management (leaseDuration, leaseState)

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

Let's create Azure Blob Storage Containers

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Naming & Immutability
What are the naming requirements for storage accounts and containers?
Storage account names (accountName) must be 3-24 characters using only numbers and lowercase letters. Container names (containerName) must be 3-63 characters using numbers, lowercase letters, and dashes, where each dash must be immediately preceded and followed by a letter or number.
What properties can't I change after creating a container?
The accountName, containerName, and immutableStorageWithVersioning properties are immutable. You’ll need to recreate the container to change these values.
Can I enable immutable storage on an existing container?
Existing containers must undergo a migration process to enable immutableStorageWithVersioning. This property can only be set to true at container creation time for new containers.
Encryption & Security
How do I enforce a specific encryption scope for all blobs?
Set defaultEncryptionScope to your encryption scope name and denyEncryptionScopeOverride to true. This prevents blobs from using different encryption scopes.
What does denyEncryptionScopeOverride do?
When set to true, it blocks override of the container’s default encryption scope, ensuring all blobs use the scope specified in defaultEncryptionScope.
How do I control public access to container data?
Use the publicAccess property to specify whether data may be accessed publicly and the level of access permitted.
Advanced Features
How do I enable object-level WORM for a container?
Set immutableStorageWithVersioning.enabled to true when creating the container. This enables Write Once Read Many protection at the object level.

Using a different cloud?

Explore storage guides for other cloud providers: