Back to Blog
5 min read

Azure Container Instances for Serverless Container Workloads

Azure Container Instances (ACI) offers the fastest and simplest way to run a container in Azure. Without managing virtual machines or adopting a higher-level service, ACI provides serverless containers with per-second billing.

When to Use ACI

ACI is ideal for:

  • Batch processing jobs
  • CI/CD build agents
  • Event-driven processing
  • Simple web applications
  • Development and testing
  • Burstable workloads from AKS (Virtual Kubelet)

Quick Start with Azure CLI

Deploy a container in seconds:

# Create a resource group
az group create --name myACIGroup --location eastus

# Deploy a container
az container create \
    --resource-group myACIGroup \
    --name mycontainer \
    --image mcr.microsoft.com/azuredocs/aci-helloworld \
    --dns-name-label aci-demo-$RANDOM \
    --ports 80

# Get the FQDN
az container show \
    --resource-group myACIGroup \
    --name mycontainer \
    --query ipAddress.fqdn \
    --output tsv

Container Groups

Container groups allow multiple containers to share lifecycle, resources, and network:

# container-group.yaml
apiVersion: 2019-12-01
location: eastus
name: multi-container-group
properties:
  containers:
  - name: web-app
    properties:
      image: nginx:alpine
      ports:
      - port: 80
      resources:
        requests:
          cpu: 1.0
          memoryInGb: 1.5
      volumeMounts:
      - name: shared-data
        mountPath: /usr/share/nginx/html
  - name: sidecar
    properties:
      image: myacr.azurecr.io/content-updater:v1
      resources:
        requests:
          cpu: 0.5
          memoryInGb: 0.5
      volumeMounts:
      - name: shared-data
        mountPath: /data
  volumes:
  - name: shared-data
    emptyDir: {}
  osType: Linux
  ipAddress:
    type: Public
    ports:
    - protocol: tcp
      port: 80
tags: {}
type: Microsoft.ContainerInstance/containerGroups

Deploy with:

az container create \
    --resource-group myACIGroup \
    --file container-group.yaml

Deploying from Azure Container Registry

# Create ACR
az acr create \
    --resource-group myACIGroup \
    --name myacr \
    --sku Basic

# Build and push image
az acr build \
    --registry myacr \
    --image myapp:v1 \
    ./src

# Enable admin user (for simple scenarios)
az acr update --name myacr --admin-enabled true

# Get credentials
ACR_USERNAME=$(az acr credential show --name myacr --query username --output tsv)
ACR_PASSWORD=$(az acr credential show --name myacr --query passwords[0].value --output tsv)

# Deploy from ACR
az container create \
    --resource-group myACIGroup \
    --name myapp \
    --image myacr.azurecr.io/myapp:v1 \
    --registry-login-server myacr.azurecr.io \
    --registry-username $ACR_USERNAME \
    --registry-password $ACR_PASSWORD \
    --dns-name-label myapp-demo \
    --ports 80

Environment Variables and Secrets

# With environment variables
az container create \
    --resource-group myACIGroup \
    --name myapp \
    --image myacr.azurecr.io/myapp:v1 \
    --environment-variables \
        'DATABASE_HOST'='myserver.database.windows.net' \
        'LOG_LEVEL'='INFO' \
    --secure-environment-variables \
        'DATABASE_PASSWORD'='secretpassword123' \
    --registry-login-server myacr.azurecr.io \
    --registry-username $ACR_USERNAME \
    --registry-password $ACR_PASSWORD

Mounting Azure Files

# Create storage account and file share
az storage account create \
    --resource-group myACIGroup \
    --name mystorageaccount \
    --sku Standard_LRS

az storage share create \
    --name myshare \
    --account-name mystorageaccount

# Get storage key
STORAGE_KEY=$(az storage account keys list \
    --resource-group myACIGroup \
    --account-name mystorageaccount \
    --query '[0].value' \
    --output tsv)

# Deploy with volume mount
az container create \
    --resource-group myACIGroup \
    --name myapp \
    --image myacr.azurecr.io/myapp:v1 \
    --azure-file-volume-account-name mystorageaccount \
    --azure-file-volume-account-key $STORAGE_KEY \
    --azure-file-volume-share-name myshare \
    --azure-file-volume-mount-path /data

Running Batch Jobs with ACI

Python script for batch processing:

# batch_processor.py
import os
import json
from azure.storage.blob import BlobServiceClient
from azure.identity import DefaultAzureCredential

def process_batch():
    connection_string = os.environ['STORAGE_CONNECTION_STRING']
    input_container = os.environ.get('INPUT_CONTAINER', 'input')
    output_container = os.environ.get('OUTPUT_CONTAINER', 'output')

    blob_service = BlobServiceClient.from_connection_string(connection_string)
    input_client = blob_service.get_container_client(input_container)
    output_client = blob_service.get_container_client(output_container)

    # Process each blob in input container
    for blob in input_client.list_blobs():
        print(f"Processing: {blob.name}")

        # Download and process
        blob_data = input_client.download_blob(blob.name).readall()
        processed_data = transform_data(blob_data)

        # Upload result
        output_blob = output_client.get_blob_client(f"processed_{blob.name}")
        output_blob.upload_blob(processed_data, overwrite=True)

        print(f"Completed: {blob.name}")

def transform_data(data):
    # Your transformation logic here
    result = data.upper()  # Simple example
    return result

if __name__ == "__main__":
    process_batch()
    print("Batch processing complete!")

Dockerfile:

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY batch_processor.py .

CMD ["python", "batch_processor.py"]

Deploy as a job:

az container create \
    --resource-group myACIGroup \
    --name batch-job \
    --image myacr.azurecr.io/batch-processor:v1 \
    --restart-policy Never \
    --environment-variables \
        'INPUT_CONTAINER'='raw-data' \
        'OUTPUT_CONTAINER'='processed-data' \
    --secure-environment-variables \
        'STORAGE_CONNECTION_STRING'='your-connection-string' \
    --cpu 2 \
    --memory 4

Virtual Network Integration

Deploy ACI into a virtual network for private connectivity:

# Create VNet and subnet
az network vnet create \
    --resource-group myACIGroup \
    --name myVNet \
    --address-prefix 10.0.0.0/16 \
    --subnet-name aci-subnet \
    --subnet-prefix 10.0.1.0/24

# Delegate subnet to ACI
az network vnet subnet update \
    --resource-group myACIGroup \
    --vnet-name myVNet \
    --name aci-subnet \
    --delegations Microsoft.ContainerInstance/containerGroups

# Deploy container in VNet
az container create \
    --resource-group myACIGroup \
    --name private-container \
    --image myacr.azurecr.io/myapp:v1 \
    --vnet myVNet \
    --subnet aci-subnet \
    --registry-login-server myacr.azurecr.io \
    --registry-username $ACR_USERNAME \
    --registry-password $ACR_PASSWORD

GPU Workloads

ACI supports GPU containers for ML inference:

az container create \
    --resource-group myACIGroup \
    --name gpu-container \
    --image myacr.azurecr.io/ml-inference:v1 \
    --sku gpu \
    --gpu-count 1 \
    --gpu-sku K80 \
    --cpu 4 \
    --memory 14

Monitoring and Logging

# View logs
az container logs \
    --resource-group myACIGroup \
    --name mycontainer

# Stream logs
az container attach \
    --resource-group myACIGroup \
    --name mycontainer

# Execute command in running container
az container exec \
    --resource-group myACIGroup \
    --name mycontainer \
    --exec-command "/bin/bash"

Conclusion

Azure Container Instances provides a lightweight, serverless approach to running containers. It excels for scenarios where you need quick deployment without infrastructure management. Combined with Azure Functions, Logic Apps, or Event Grid, ACI becomes a powerful tool for event-driven containerized workloads.

For long-running services or complex orchestration, consider AKS. But for batch jobs, burst workloads, and simple applications, ACI offers unmatched simplicity and cost efficiency.

Michael John Pena

Michael John Pena

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.