Skip to main content

Theoretical Foundation: Create and Configure a Container in Azure Blob Storage


1. Initial Intuition​

Imagine that a Storage Account is a warehouse. Inside this warehouse, you don't randomly throw boxes on the floor: you organize the space into sections or aisles, each with its own label and access rules. In Azure Blob Storage, these sections are called containers.

A container is the organizational unit within Blob Storage. It groups related blobs (files) and is the level where you define access settings, lifecycle policies, and replication rules.

Every blob in Azure Blob Storage must exist within a container. There are no "loose" blobs in a Storage Account.


2. Context​

2.1 Blob Storage Hierarchy​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

2.2 Why containers exist​

Blob Storage is a flat namespace: there's no real directory hierarchy like in a file system. A container is the only real organizational layer. Everything below it (what appears to be subfolders) is actually a prefix in the blob name.

For example, a blob named reports/2025/january/sales.xlsx isn't inside real folders. The entire name is the blob identifier, and the slash / is just a conventional character used to simulate hierarchy.

2.3 What you configure at the container level​

The container is the level where you define:

  • Public access level (who can access without authentication)
  • Stored Access Policies (for SAS tokens)
  • Default Encryption Scope (specific encryption key)
  • Immutability Policies (WORM: Write Once Read Many)
  • Container metadata (custom key-value pairs)

3. Concept Construction​

3.1 Blob types​

Before understanding containers in depth, you need to know what they store. Azure Blob Storage has three blob types, and each container can contain any combination of them:

Block Blob:

  • General-purpose blob for unstructured files
  • Divided into blocks up to 4,000 MiB each
  • Maximum size: 190.7 TiB
  • Uses: images, videos, documents, backups, datasets

Append Blob:

  • Optimized for append operations at the end
  • Doesn't allow modifying existing blocks
  • Maximum size: 195 GiB
  • Uses: logs, telemetry data, event streams

Page Blob:

  • Organized in 512-byte pages
  • Allows efficient random read and write
  • Maximum size: 8 TiB
  • Uses: unmanaged VM disks (VHDs)

Non-obvious behavior: You don't choose the blob type when creating the container. The type is defined when creating/uploading each blob individually. A single container can have all three types coexisting.


3.2 Container public access level​

This is one of the most important and most misunderstood concepts in Blob Storage. There are three levels:

Private (default):

  • No anonymous access
  • All access requires authentication (key, SAS, Azure AD)
  • Recommended for all data that isn't intentionally public

Blob:

  • Individual blobs can be accessed anonymously if you know the complete URL
  • Cannot list container blobs anonymously
  • Useful when you want specific URLs to be public without exposing the inventory

Container:

  • Full anonymous access: anyone can list all blobs and access any blob
  • Never use for sensitive data
  • Useful only for truly public content (public website assets)
LevelBlob reading with URLBlob listingUse
PrivateNo (requires auth)NoDefault for all data
BlobYes (known URL)NoPublic download links
ContainerYesYesCompletely public assets

Critical security point: Since 2023, Azure added a Storage Account level setting called "Allow Blob Anonymous Access" that controls whether public access can be enabled on any container in the account. If this setting is false (recommended for production), no container in the account can have public access, regardless of individual container configuration.


3.3 Virtual directories and prefixes​

As mentioned, Blob Storage doesn't have real directories. What appears to be a folder is a prefix in the blob name:

  • Actual blob: reports/2025/january/sales.xlsx
  • Container: data
  • Complete URL: https://myaccount.blob.core.windows.net/data/reports/2025/january/sales.xlsx

The listing API allows filtering blobs by prefix using the prefix parameter, which simulates "folder" navigation. Storage Explorer and the portal render these prefixes as folders visually.

When you create a "folder" in the portal or Storage Explorer, what actually happens is that an empty blob (a placeholder) with the name folder/ is created. Some operations remove this placeholder automatically.


3.4 Immutability Policies (WORM)​

Containers can be configured with immutability policies that prevent blob modification or deletion for a defined period. There are two types:

Time-based Retention Policy:

  • Defines a retention period (in days) during which blobs cannot be deleted or modified
  • After the period, blobs can be deleted normally
  • Can be applied at container or individual blob level

Legal Hold:

  • Indefinite lock without a defined deadline
  • Removed only when the hold is explicitly released
  • Used for legal processes and audits
100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

Critical behavior: Once a Time-based Retention Policy is locked, the retention period cannot be reduced, only increased. This is intentional for regulatory compliance (FINRA, SEC, CFTC). Always test in non-production environments before locking.


3.5 Stored Access Policies​

A Stored Access Policy is an access policy stored at the container level that can be referenced by multiple SAS tokens. The advantage is that you can revoke or modify access for all SAS tokens referencing a policy by simply updating or deleting the policy, without needing to invalidate each token individually.


4. Structural View​

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

5. Practical Operation​

5.1 Container naming​

The naming rules are strict and failures here cause hard-to-diagnose errors:

  • 3 to 63 characters
  • Only lowercase letters, numbers, and hyphens
  • Must start with letter or number
  • Cannot have consecutive hyphens
  • The name $root is a special reserved container (the "root container")
  • The name $web is reserved for static website hosting

5.2 The $web container and static hosting​

When you enable Static Website on a Storage Account, Azure automatically creates a special container called $web. Files placed in this container are served directly as a static website via a separate endpoint:

https://myaccount.z13.web.core.windows.net

This endpoint is different from the normal blob endpoint. It serves files like a web server, including an index file (index.html) and a customizable 404 error page.


5.3 Leases on containers and blobs​

A lease is a temporary lock that can be applied to a container or blob. While the lease is active:

  • Container lease: Only the lease holder can delete the container
  • Blob lease: Only the lease holder can modify or delete the blob

Lease states:

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

Leases are used by tools like AzCopy and Storage Explorer during transfers to ensure other processes don't modify the blob while the operation is in progress.


5.4 Versioning and Snapshots in container context​

When Blob Versioning is enabled on the Storage Account (account-level setting, not container):

  • Each blob modification automatically creates a new version
  • The current version is the most recent
  • Previous versions are read-only
  • Versions are stored in the same container as the original blob

When you manually create a Snapshot:

  • It's a read-only copy of the blob at a specific moment
  • Identified by creation date and time
  • Stored in the same container
  • URL has the suffix ?snapshot=2025-01-15T10:30:00.0000000Z

6. Implementation Methods​

6.1 Azure Portal​

When to use: One-time creation, exploration, public access configuration, policy application.

In portal: Storage Account > Containers > + Container

You define:

  • Container name
  • Public access level (if Allow Anonymous Access is enabled on the account)
  • Default Encryption Scope (optional)

Limitation: Doesn't support bulk creation or Immutability Policy configuration directly during creation (it's a separate step).


6.2 Azure CLI​

Creating a container:

# Simple container (private, default)
az storage container create \
--account-name myaccount \
--name images \
--auth-mode login

# Container with public access at blob level
az storage container create \
--account-name myaccount \
--name public-assets \
--public-access blob \
--auth-mode login

# Container with default Encryption Scope
az storage container create \
--account-name myaccount \
--name finance-data \
--default-encryption-scope FinanceScope \
--prevent-encryption-scope-override true \
--auth-mode login

Listing containers:

az storage container list \
--account-name myaccount \
--auth-mode login \
--output table

Configuring metadata:

az storage container metadata update \
--account-name myaccount \
--name images \
--metadata department=marketing environment=production \
--auth-mode login

Applying Stored Access Policy:

az storage container policy create \
--account-name myaccount \
--container-name images \
--name ReadOnlyPolicy \
--permissions r \
--expiry 2025-12-31 \
--auth-mode login

Configuring Time-based Retention Policy:

# Create policy (unlocked state)
az storage container immutability-policy create \
--account-name myaccount \
--resource-group myRG \
--container-name compliance-data \
--period 365

# Lock the policy (irreversible for reduction)
az storage container immutability-policy lock \
--account-name myaccount \
--resource-group myRG \
--container-name compliance-data \
--if-match "<policy-etag>"

6.3 Azure PowerShell​

# Create context
$ctx = New-AzStorageContext `
-StorageAccountName "myaccount" `
-UseConnectedAccount

# Create private container
New-AzStorageContainer `
-Name "images" `
-Context $ctx

# Create container with public access
New-AzStorageContainer `
-Name "public-assets" `
-Context $ctx `
-Permission Blob

# Upload file to container
Set-AzStorageBlobContent `
-Container "images" `
-File "/local/path/photo.jpg" `
-Blob "products/photo.jpg" `
-Context $ctx `
-StandardBlobTier Hot

# List blobs with prefix (simulate folder navigation)
Get-AzStorageBlob `
-Container "images" `
-Prefix "products/" `
-Context $ctx

6.4 Bicep​

// Private container
resource container 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = {
name: '${storageAccount.name}/default/images'
properties: {
publicAccess: 'None'
defaultEncryptionScope: 'FinanceScope'
denyEncryptionScopeOverride: true
metadata: {
department: 'marketing'
environment: 'production'
}
}
}

// Container with Immutability Policy (unlocked)
resource complianceContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = {
name: '${storageAccount.name}/default/compliance-data'
properties: {
publicAccess: 'None'
immutableStorageWithVersioning: {
enabled: true
}
}
}

6.5 REST API​

For scenarios where neither CLI nor SDK are available:

# Create container via REST API with SAS token
curl -X PUT \
"https://myaccount.blob.core.windows.net/mycontainer?restype=container&<SAS-TOKEN>" \
-H "x-ms-version: 2023-01-03" \
-H "x-ms-blob-public-access: blob" \
-H "Content-Length: 0"

7. Control and Security​

7.1 Layered access control​

Access to a container and its blobs is determined by a chain evaluation:

100%
Scroll para zoom Β· Arraste para mover Β· πŸ“± Pinch para zoom no celular

7.2 Relevant RBAC roles for containers​

RoleWhat it allows
Storage Blob Data OwnerRead, write, delete and ACL control (ADLS Gen2)
Storage Blob Data ContributorRead, write and delete blobs
Storage Blob Data ReaderRead-only access to blobs
Storage Blob DelegatorCan generate User Delegation SAS tokens

Important distinction: Storage Account Contributor is a control plane role (manage the account, its settings). It does not grant access to blob data. For data access, Storage Blob Data * roles are necessary.


7.3 Soft Delete for containers and blobs​

Blob Soft Delete: When enabled on the Storage Account, deleted blobs remain in "soft-deleted" state for a configurable period (1 to 365 days) before being permanently removed. During this period, they can be restored.

Container Soft Delete: Similar, but for entire containers. A deleted container remains "soft-deleted" and can be restored with all its blobs.

# Enable container soft delete
az storage account blob-service-properties update \
--account-name myaccount \
--resource-group myRG \
--container-delete-retention-days 30 \
--enable-container-delete-retention true

# Enable blob soft delete
az storage account blob-service-properties update \
--account-name myaccount \
--resource-group myRG \
--delete-retention-days 7 \
--enable-delete-retention true

# List soft-deleted containers
az storage container list \
--account-name myaccount \
--include-deleted \
--auth-mode login

# Restore soft-deleted container
az storage container restore \
--account-name myaccount \
--deleted-container-name images \
--deleted-container-version <version-id> \
--auth-mode login

8. Decision Making​

8.1 Container public access level​

SituationAccess levelReason
Customer, financial, personal dataPrivateNo sensitive data should be public
Public website assets (CSS, JS, images)Blob or ContainerPublic access required
Temporary download linksPrivate + SASControl with expiration
CDN serving contentBlobCDN authenticates, end user doesn't need to
Regulatory compliancePrivate + ImmutabilityFull protection against modification
Long-term audit logsPrivate + Archive tierLow cost, rare access

8.2 Container organization​

ApproachWhen to useTrade-off
One container per data type (images, videos, docs)Homogeneous data with same configurationsSimple, but no security isolation between data
One container per applicationMultiple applications in same accountGood isolation per app
One container per departmentDifferent teams with sensitive dataAllows granular RBAC per container
One container per environment (prod, dev, test)Different lifecycles and policiesMore containers, but distinct policies
Single container with prefixesHuge volume of blobs with same patternLower overhead, but no isolation

8.3 Immutability: Locked vs Unlocked​

SituationPolicy stateReason
SEC Rule 17a-4 regulatory complianceLockedRegulation requires irreversible immutability
Policy testing before productionUnlockedAllows adjustments and cancellation
Legal data in active processLegal HoldNo defined timeframe, explicit release
Backups with guaranteed retentionLocked with defined periodProtection against ransomware

9. Best Practices​

  • Disable "Allow Blob Anonymous Access" at Storage Account level in production environments, unless public access is explicitly needed. This prevents any container in the account from being accidentally configured as public.
  • Use consistent prefixes to organize blobs within containers: <year>/<month>/<day>/file for logs, <category>/<subcategory>/file for assets.
  • Enable Soft Delete for containers and blobs with at least 7 days retention in production. The additional cost is minimal compared to the risk of data loss.
  • Separate data by lifecycle in different containers. Data that should go to Archive after 90 days fits better in a dedicated container with lifecycle policy targeting that container.
  • Use Stored Access Policies instead of ad-hoc SAS tokens when you need multiple tokens with the same permissions. Facilitates centralized revocation.
  • Apply metadata to containers with environment, team, project, and cost-center to facilitate governance and cost tracking.
  • For compliance containers, use Immutability Policy in Unlocked state first, test in non-production and only lock when you're absolutely sure of the retention period.
  • Never use Storage Account access keys directly in applications. Prefer User Delegation SAS (generated with Azure AD credentials) or RBAC.

10. Common Errors​

ErrorWhy it happensHow to avoid
Public container exposes sensitive dataContainer access configuration not verifiedAudit via Azure Policy: "Storage account public access should be disallowed"
Cannot delete container with ImmutabilityActive policy with non-expired retention periodCheck policy state before attempting deletion
"Blob not found" in public container"Blob" level access but attempting to list without authentication"Blob" level doesn't allow anonymous listing, only URL access
Soft delete doesn't restore blobsSoft delete enabled after blobs were already deletedEnable soft delete before any critical operation
Containers don't appear in portal after deletionContainer soft delete activated, container is in deleted stateUse az storage container list --include-deleted
SAS token for container cannot list blobsPermission l (list) not included in SASInclude l in SAS permissions when listing is needed
Naming error during creationUppercase letters or underscores in nameUse only lowercase, numbers and hyphens
Lifecycle policy doesn't move blobs to ArchiveContainer doesn't have Archive tier available (Premium account)Archive is only available in Standard GPv2

11. Operation and Maintenance​

11.1 Lifecycle policies (Lifecycle Management)​

Defined at Storage Account level but applied per container via filters:

{
"rules": [
{
"name": "images-lifecycle",
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["images/"]
},
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 180 },
"delete": { "daysAfterModificationGreaterThan": 730 }
},
"snapshot": {
"delete": { "daysAfterCreationGreaterThan": 90 }
}
}
}
}
]
}

Via CLI:

az storage account management-policy create \
--account-name myaccount \
--resource-group myRG \
--policy @lifecycle-policy.json

11.2 Container monitoring​

Relevant metrics in Azure Monitor:

MetricWhat it indicates
BlobCountNumber of blobs per container (filter by ContainerName)
BlobCapacityCapacity used in bytes per container
TransactionsNumber of operations (may indicate anomalous usage)
SuccessE2ELatencyOperation latency

Configure alerts to detect unexpected growth of BlobCapacity in containers with expected quotas.


11.3 Important limits​

ResourceLimit
Containers per Storage AccountUnlimited
Blobs per containerUnlimited
Maximum size of a Block Blob190.7 TiB
Maximum size of an Append Blob195 GiB
Maximum size of a Page Blob8 TiB
Snapshots per blobUnlimited (practice: manage lifecycle)
Stored Access Policies per container5

12. Integration and Automation​

12.1 Event Grid: reacting to container events​

Containers emit events to Azure Event Grid:

  • Microsoft.Storage.BlobCreated
  • Microsoft.Storage.BlobDeleted
  • Microsoft.Storage.BlobRenamed (ADLS Gen2 only)

This allows building serverless pipelines:

az eventgrid event-subscription create \
--name blob-created-trigger \
--source-resource-id <storage-account-id> \
--endpoint <azure-function-url> \
--included-event-types Microsoft.Storage.BlobCreated \
--subject-begins-with /blobServices/default/containers/images/

The --subject-begins-with filter ensures only events from the images container trigger the function.


12.2 Azure Policy for container governance​

Relevant built-in policies:

# Ensure public access is blocked
az policy assignment create \
--name "deny-blob-public-access" \
--policy "d9844e8a-1437-4aeb-a32c-0761373107d4" \
--scope "/subscriptions/<sub-id>"

# Audit containers without soft delete enabled
az policy assignment create \
--name "audit-soft-delete" \
--policy "1a87f16b-6e53-4f10-8d29-9f44d3e2d2b2" \
--scope "/subscriptions/<sub-id>"

12.3 ADLS Gen2: containers as file systems​

When the Storage Account has Hierarchical Namespace (HNS) enabled, Blob Storage containers become file systems of Azure Data Lake Storage Gen2:

  • Real directories (not just prefixes)
  • POSIX permissions per directory and file (ACLs)
  • Atomic directory rename operations
  • Superior performance for analytics workloads

Nomenclature changes: in ADLS Gen2 context, what would be a container is called a filesystem, but technically it's the same resource.


13. Final Summary​

Essential concepts:

  • A container is the only real organizational unit in Blob Storage. Every blob exists within a container.
  • Blob Storage has a flat namespace: what appears to be folder hierarchy are prefixes in blob names.
  • Containers have three public access levels: Private (default), Blob (specific URL), and Container (listing + public read).
  • The "Allow Blob Anonymous Access" setting on the account controls whether any container can have public access.

Critical differences:

  • Blob vs Container access level: "Blob" level allows URL access but not listing. "Container" level allows both.
  • Container vs blob soft delete: These are separate configurations with independent retention periods.
  • Storage Account Contributor vs Storage Blob Data Contributor: The first manages the account (control plane). The second accesses data (data plane).
  • Immutability Locked vs Unlocked: Unlocked can be cancelled. Locked can only have the period increased, never reduced or removed.
  • Stored Access Policy vs direct SAS token: SAP allows centralized revocation. Direct SAS cannot be revoked individually.

What needs to be remembered:

  • Container names: 3 to 63 characters, only lowercase, numbers and hyphens.
  • Maximum of 5 Stored Access Policies per container.
  • Locked Immutability Policy is irreversible for period reduction.
  • Soft Delete must be enabled before deleting data; doesn't protect deletions prior to enablement.
  • Archive tier is only available in Standard GPv2, not Premium accounts.
  • The $web container is reserved for Static Website hosting.
  • In ADLS Gen2, containers are called filesystems and support real directories and POSIX ACLs.