Skip to content

Azure Blob Storage for Images

This guide provides a comprehensive step-by-step approach to using Azure Blob Storage for image storage, including security configurations and integration with GitHub Static Web Apps.

Before you begin, ensure you have:

  • An active Azure subscription
  • Azure CLI installed and configured
  • Basic understanding of Azure Resource Groups
  • Node.js installed (for GitHub Actions integration)
  1. Navigate to Azure Portal
  2. Click Create a resource > Storage > Storage account
  3. Fill in the required details:
    • Subscription: Select your subscription
    • Resource group: Create new or use existing
    • Storage account name: Must be globally unique (3-24 characters, lowercase, numbers only)
    • Region: Choose closest to your users
    • Performance: Standard (for most use cases)
    • Redundancy: LRS (Locally Redundant Storage) for cost-effective option
Terminal window
# Set variables
RESOURCE_GROUP="rg-image-storage"
STORAGE_ACCOUNT="myimagestore$(openssl rand -hex 4)"
LOCATION="eastus"
# Create resource group
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
# Create storage account
az storage account create \
--name $STORAGE_ACCOUNT \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--sku Standard_LRS \
--kind StorageV2 \
--https-only true \
--allow-blob-public-access true
  1. Navigate to your Storage Account
  2. Go to Data Storage > Containers
  3. Click + Container
  4. Configure container:
    • Name: images (or your preferred name)
    • Public access level: Choose based on your needs:
      • Private: No anonymous access
      • Blob: Anonymous read access for blobs only
      • Container: Anonymous read access for container and blobs
Terminal window
# Get storage account key
STORAGE_KEY=$(az storage account keys list \
--resource-group $RESOURCE_GROUP \
--account-name $STORAGE_ACCOUNT \
--query '[0].value' -o tsv)
# Create container for public images
az storage container create \
--name images \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--public-access blob
# Create container for private images
az storage container create \
--name private-images \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--public-access off
Terminal window
# Upload a single image
az storage blob upload \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--container-name images \
--name "logo.png" \
--file "./local-logo.png" \
--content-type "image/png"
# Upload multiple images
for file in ./images/*; do
filename=$(basename "$file")
az storage blob upload \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--container-name images \
--name "$filename" \
--file "$file" \
--overwrite
done

JavaScript/Node.js Example:

const { BlobServiceClient } = require('@azure/storage-blob');
async function uploadImage() {
const connectionString = "DefaultEndpointsProtocol=https;AccountName=...";
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobServiceClient.getContainerClient('images');
const blockBlobClient = containerClient.getBlockBlobClient('logo.png');
// Upload from file
await blockBlobClient.uploadFile('./local-logo.png', {
blobHTTPHeaders: {
blobContentType: 'image/png'
}
});
console.log('Image uploaded successfully!');
console.log(`Image URL: ${blockBlobClient.url}`);
}

🌐 Step 4: Configure Custom Domain (Optional)

Section titled “🌐 Step 4: Configure Custom Domain (Optional)”
Terminal window
# Add custom domain to storage account
az storage account update \
--name $STORAGE_ACCOUNT \
--resource-group $RESOURCE_GROUP \
--custom-domain "images.yourdomain.com"

Add a CNAME record in your DNS provider:

  • Name: images
  • Value: mystorageaccount.blob.core.windows.net
Terminal window
# Enable storage analytics
az storage logging update \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--services b \
--log rwd \
--retention 7
Terminal window
# Create action group for notifications
az monitor action-group create \
--name "storage-alerts" \
--resource-group $RESOURCE_GROUP \
--action email admin admin@yourdomain.com
# Create alert rule for high storage usage
az monitor metrics alert create \
--name "High Storage Usage" \
--resource-group $RESOURCE_GROUP \
--scopes "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT" \
--condition "avg UsedCapacity > 50000000000" \
--action "storage-alerts"

For public containers, images are accessible via direct URLs:

https://<storage-account>.blob.core.windows.net/<container>/<blob-name>

Example:

https://myimagestore1234.blob.core.windows.net/images/logo.png

For private containers, you’ll need to generate SAS (Shared Access Signature) tokens:

Terminal window
# Generate SAS token for specific blob
az storage blob generate-sas \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--container-name private-images \
--name "private-logo.png" \
--permissions r \
--expiry "2024-12-31T23:59:59Z" \
--https-only
  1. Use CDN: Enable Azure CDN for global distribution
  2. Optimize Image Formats: Use WebP, AVIF for modern browsers
  3. Implement Caching: Set appropriate cache headers
  4. Use Proper Naming: Use consistent, descriptive blob names
  1. Choose Right Storage Tier: Hot, Cool, or Archive based on access patterns
  2. Lifecycle Management: Automatically move old images to cheaper tiers
  3. Monitor Costs: Set up cost alerts and budgets
  4. Delete Unused Images: Regular cleanup of unused assets
  1. Use Private Containers: When possible, keep images private
  2. Implement SAS Tokens: For controlled access to private content
  3. Enable Encryption: All data is encrypted at rest by default
  4. Regular Access Reviews: Monitor who has access to storage accounts

Error: Storage account name not available

  • Solution: Try a different name; storage account names must be globally unique

Error: Cannot access blob

  • Check container public access settings
  • Verify SAS token hasn’t expired for private containers

Slow image loading

  • Enable Azure CDN
  • Optimize image sizes and formats
  • Check network connectivity
Terminal window
# List all blobs in container
az storage blob list \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--container-name images \
--output table
# Get blob properties
az storage blob show \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--container-name images \
--name logo.png
# Copy blob between containers
az storage blob copy start \
--source-container images \
--source-blob logo.png \
--destination-container backup \
--destination-blob logo-backup.png \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY