Azure Container Instances: Run Containers Without Managing Servers
Azure Container Instances (ACI) runs Docker containers on-demand without requiring you to provision or manage any virtual machines. You describe the container (image, CPU, memory, ports), and Azure starts it within seconds. ACI is the simplest way to run a container in Azure — faster than AKS, cheaper than a VM, and zero infrastructure to manage. This page explains when it fits and when you should use something else.
ACI versus other container options in Azure
| Service | Best for | What you manage |
|---|---|---|
| ACI | One-off tasks, batch jobs, dev/test, simple jobs | Container definition only — no cluster, no nodes |
| Azure Container Apps | Scalable microservices, event-driven apps, HTTP APIs | Container config and scaling rules — no cluster management |
| App Service (containers) | Web apps and APIs with managed HTTPS and deployment slots | App settings and deployment config |
| AKS | Complex microservices, stateful workloads, custom networking | Kubernetes cluster configuration, node pools, upgrades |
ACI is not designed for long-running, load-balanced services. It has no built-in autoscaling, no traffic routing across multiple replicas, and no health-check-driven restarts that a production service needs. Think of ACI as a fast, lightweight way to run a container job — not as a web server platform.
Running your first container
Running a container with ACI takes one CLI command:
# Run a public container image — an NGINX web server
az container create \
--resource-group my-rg \
--name my-nginx \
--image nginx:latest \
--cpu 1 \
--memory 1 \
--ports 80 \
--ip-address Public \
--dns-name-label my-nginx-demo-$(date +%s)Within 10–20 seconds, a container is running. The output includes a FQDN like my-nginx-demo-1234567890.eastus.azurecontainer.io. Open that in a browser to reach the NGINX default page.
# Check container status
az container show \
--resource-group my-rg \
--name my-nginx \
--query "{status: instanceView.state, ip: ipAddress.ip, fqdn: ipAddress.fqdn}" \
--output table
# View container logs
az container logs --resource-group my-rg --name my-nginx
# Delete the container
az container delete --resource-group my-rg --name my-nginx --yesThe best use case: batch and scheduled jobs
ACI’s strengths shine in batch processing. Consider a nightly data transformation job that takes an hour to run, then exits. Running this on a VM means the VM idles for 23 hours every day. ACI charges per second of actual container execution — you pay only while the job runs.
# Run a batch job container that exits when done
az container create \
--resource-group my-rg \
--name data-processor \
--image myacr.azurecr.io/processor:latest \
--cpu 2 \
--memory 4 \
--restart-policy Never \
--environment-variables \
STORAGE_ACCOUNT=mystorageaccount \
INPUT_CONTAINER=raw-data \
OUTPUT_CONTAINER=processed-data \
--secure-environment-variables \
STORAGE_KEY=<secret-key>The —restart-policy Never flag means ACI does not restart the container after it exits. Combined with —restart-policy OnFailure for retry logic, this gives you simple job execution semantics: run the container, complete the job, clean up.
For a more production-ready approach, trigger ACI from Azure Logic Apps, Azure Data Factory, or an Azure Function on a schedule — rather than using the CLI directly. These orchestration services handle scheduling, retries, and alerting on failure.
Pulling images from a private registry
When your container image is in a private Azure Container Registry, ACI needs credentials to pull it. The recommended approach is to use a managed identity rather than a username/password:
# Create the container using a managed identity to pull from ACR
az container create \
--resource-group my-rg \
--name my-app \
--image myacr.azurecr.io/myapp:latest \
--cpu 1 \
--memory 2 \
--acr-identity /subscriptions/.../userAssignedIdentities/my-aci-identity \
--assign-identity /subscriptions/.../userAssignedIdentities/my-aci-identityThe user-assigned managed identity needs the AcrPull role on the Azure Container Registry. See Azure Container Registry overview for how to set that up.
Container groups: multiple containers together
ACI supports container groups — a concept similar to Kubernetes pods. Multiple containers in a group share a network namespace (they communicate via localhost) and are scheduled on the same underlying host. Use container groups to run sidecars:
# container-group.yaml
apiVersion: 2021-09-01
name: my-container-group
type: Microsoft.ContainerInstance/containerGroups
location: eastus
properties:
containers:
- name: app
properties:
image: myacr.azurecr.io/myapp:latest
resources:
requests:
cpu: 1
memoryInGb: 1
ports:
- port: 8080
- name: log-collector
properties:
image: myacr.azurecr.io/log-agent:latest
resources:
requests:
cpu: 0.5
memoryInGb: 0.5
ipAddress:
type: Public
ports:
- port: 8080
osType: Linuxaz container create --resource-group my-rg --file container-group.yamlLimitations to know before committing
- No horizontal scaling. ACI runs a single container group. If you need multiple replicas with load balancing, use Azure Container Apps or AKS.
- No persistent local storage. The container’s local filesystem is ephemeral. Data written to the container’s disk is lost when the container stops. Mount an Azure Files share for persistence.
- Public IP per container group. ACI does not sit behind a shared load balancer by default. Each container group with a public IP gets its own IP address and DNS name. For multiple instances of the same service, use another compute option.
- No GPU support in all regions. ACI has limited GPU instance availability compared to VM-based options. Check GPU ACI availability in your target region before building on it.
Common ACI mistakes
- Using ACI for a long-running web service. ACI has no built-in load balancing across replicas, no autoscaling, and no health-check-driven replacement. A web service that needs to handle fluctuating traffic and recover from failures needs AKS, Container Apps, or App Service.
- Storing secrets in environment variables with —environment-variables. Environment variables set with the non-secure flag appear in plaintext in the Azure portal and deployment history. Use
—secure-environment-variablesfor sensitive values — they are encrypted and not visible in the portal after submission. - Forgetting to delete containers after batch jobs. ACI charges per second while the container exists, even if it has exited. A container in Terminated state still accrues storage charges for its definition. Delete containers after jobs complete, or use
—restart-policy Neverand automate deletion.
Summary
- ACI runs containers on-demand without managing VMs or clusters. Start time is typically under 30 seconds.
- Best uses: batch jobs, data processing tasks, scheduled jobs, CI/CD steps, and quick testing of containerised workloads.
- Not suitable for load-balanced, autoscaling web services — use Container Apps, App Service, or AKS for those.
- Container groups support sidecars: multiple containers sharing a network namespace, similar to a Kubernetes pod.
- Use managed identities to pull from Azure Container Registry instead of storing credentials in the container definition.
Frequently asked questions
How quickly does an Azure Container Instance start?
Most ACI containers start in under 10 seconds from the moment the API call is made, assuming the image is already pulled. Larger images or cold-start scenarios (first pull) can take 30–90 seconds. This is significantly faster than VM-based solutions.
Can ACI run multiple containers together?
Yes. ACI supports container groups — multiple containers in a single logical deployment that share a network namespace and can communicate via localhost. This is similar to a Kubernetes pod. Use container groups to run a sidecar container alongside your application container.
Does ACI support persistent storage?
Yes. You can mount Azure File Shares (SMB) or Azure Blob Storage (FUSE) into ACI containers. The mount appears as a directory inside the container, and data persists beyond the container lifecycle. This is useful for batch jobs that need to write output that outlasts the container.