Container Apps
Introduction
Section titled “Introduction”Azure Container Apps is a serverless container platform for running containerized applications and microservices without managing Kubernetes infrastructure. Applications are deployed into a managed environment, receive an HTTPS ingress endpoint, and are versioned through revisions, while background and scheduled work runs as jobs. For more information, see Azure Container Apps overview.
LocalStack for Azure provides a local environment for building and testing applications that use Azure Container Apps. The supported APIs are available on our API Coverage section, which provides information on the extent of Container Apps’ integration with LocalStack.
Getting started
Section titled “Getting started”This guide is designed for users new to Container Apps and assumes basic knowledge of the Azure CLI and our lstk az proxy.
Launch LocalStack using your preferred method. For more information, see Introduction to LocalStack for Azure. Once the container is running, enable Azure CLI interception by running:
lstk az start-interceptionThis command points the az CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:
lstk az stop-interceptionThis reconfigures the az CLI to send commands to the official Azure management REST API.
Create a resource group
Section titled “Create a resource group”Create a resource group that will contain your Container Apps resources:
az group create \ --name rg-aca-demo \ --location westeurope{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-aca-demo", "location": "westeurope", "managedBy": null, "name": "rg-aca-demo", "properties": { "provisioningState": "Succeeded" }, "tags": null, "type": "Microsoft.Resources/resourceGroups"}Create a Container Apps environment
Section titled “Create a Container Apps environment”Create a managed environment that will host your container apps and jobs:
az containerapp env create \ --name my-environment \ --resource-group rg-aca-demo \ --location westeurope \ --logs-destination none{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-aca-demo/providers/Microsoft.App/managedEnvironments/my-environment", "location": "westeurope", "name": "my-environment", "properties": { "appLogsConfiguration": { "destination": null }, "defaultDomain": "nicesmoke-4f9d21-westeurope.aca.azure.localhost.localstack.cloud", "provisioningState": "Succeeded" }, "type": "Microsoft.App/managedEnvironments" ...}Each environment receives a defaultDomain under aca.azure.localhost.localstack.cloud.
This domain resolves to 127.0.0.1, so the ingress endpoints of apps in the environment are directly reachable from your machine.
Create a container app
Section titled “Create a container app”Create a container app with external HTTP ingress:
az containerapp create \ --name quickstart \ --resource-group rg-aca-demo \ --environment my-environment \ --image mcr.microsoft.com/k8se/quickstart:latest \ --ingress external \ --target-port 80 \ --cpu 0.5 --memory 1Gi \ --min-replicas 1 --max-replicas 3 \ --revision-suffix v1{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-aca-demo/providers/Microsoft.App/containerapps/quickstart", "location": "westeurope", "name": "quickstart", "properties": { "configuration": { "activeRevisionsMode": "Single", "ingress": { "allowInsecure": false, "external": true, "fqdn": "quickstart--nicesmoke-4f9d21-westeurope.aca.azure.localhost.localstack.cloud", "targetPort": 80, "transport": "Auto" } }, "latestReadyRevisionName": "quickstart--v1", "latestRevisionName": "quickstart--v1", "provisioningState": "Succeeded", "runningStatus": "Running", "template": { "containers": [ { "image": "mcr.microsoft.com/k8se/quickstart:latest", "name": "quickstart", "resources": { "cpu": 0.5, "memory": "1Gi" } } ], "revisionSuffix": "v1", "scale": { "maxReplicas": 3, "minReplicas": 1 } } }, "type": "Microsoft.App/containerApps" ...}Invoke the container app
Section titled “Invoke the container app”Retrieve the ingress FQDN and send a request to the running app.
The FQDN is served by the LocalStack gateway on port 4566 with a valid TLS certificate:
FQDN=$(az containerapp show \ --name quickstart \ --resource-group rg-aca-demo \ --query "properties.configuration.ingress.fqdn" \ --output tsv)
curl -s -o /dev/null -w "%{http_code}\n" "https://$FQDN:4566/"200You can also open https://$FQDN:4566/ in your browser to see the welcome page of the quickstart image.
Manage secrets
Section titled “Manage secrets”Add a secret to the container app:
az containerapp secret set \ --name quickstart \ --resource-group rg-aca-demo \ --secrets api-key=top-secretList the secrets, including their values:
az containerapp secret list \ --name quickstart \ --resource-group rg-aca-demo \ --show-values[ { "identity": null, "keyVaultUrl": null, "name": "api-key", "value": "top-secret" }]Secrets can be referenced from environment variables via secretref:, mounted as secret volumes, and defined as Key Vault references that are resolved from the emulated Key Vault.
Update the app and work with revisions
Section titled “Update the app and work with revisions”Update the container app with a new environment variable. Every change to the app template mints a new revision:
az containerapp update \ --name quickstart \ --resource-group rg-aca-demo \ --revision-suffix v2 \ --set-env-vars GREETING=helloList the revisions of the app:
az containerapp revision list \ --name quickstart \ --resource-group rg-aca-demo \ --query "[].name" \ --output tsvquickstart--v1quickstart--v2In the default Single revisions mode, the latest ready revision serves all traffic and older revisions are deactivated automatically.
In Multiple mode, revisions stay active and can be deactivated and re-activated with az containerapp revision deactivate and az containerapp revision activate.
Run a job
Section titled “Run a job”Create a manually triggered job in the same environment:
az containerapp job create \ --name my-job \ --resource-group rg-aca-demo \ --environment my-environment \ --trigger-type Manual \ --replica-timeout 1800 \ --image mcr.microsoft.com/k8se/quickstart-jobs:latest \ --cpu 0.25 --memory 0.5GiStart an execution of the job. The execution runs as a real container and the command returns once it reaches a terminal state:
az containerapp job start \ --name my-job \ --resource-group rg-aca-demo{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-aca-demo/providers/Microsoft.App/jobs/my-job/executions/my-job-8b31fc2", "name": "my-job-8b31fc2"}List the executions of the job to inspect their status:
az containerapp job execution list \ --name my-job \ --resource-group rg-aca-demo \ --query "[].{name:name, status:properties.status}"[ { "name": "my-job-8b31fc2", "status": "Succeeded" }]Delete and verify
Section titled “Delete and verify”Delete the container app and the job, then delete the environment:
az containerapp delete \ --name quickstart \ --resource-group rg-aca-demo \ --yes
az containerapp job delete \ --name my-job \ --resource-group rg-aca-demo \ --yes
az containerapp env delete \ --name my-environment \ --resource-group rg-aca-demo \ --yesDeleting a container app removes its containers from the local cluster. An environment can only be deleted once all apps, jobs, and managed certificates in it have been removed.
Verify the resource group is now empty:
az containerapp list \ --resource-group rg-aca-demo[]Features
Section titled “Features”- Real container execution: Container apps and job executions run as real containers on a local Kubernetes (k3d) cluster that LocalStack provisions per managed environment. Set
LS_AZURE_CONTAINER_APPS_RUNTIME=0to manage Container Apps resources in control-plane-only mode without starting containers. - Live HTTPS ingress: Every app with ingress gets an FQDN that resolves to
127.0.0.1and is served with a valid TLS certificate. CORS policies, IP security restrictions, HTTPS redirects, and session affinity are enforced at the ingress. - Revisions: Both
SingleandMultiplerevision modes are supported, including revision minting on template changes, activation and deactivation, and per-revision FQDNs. - Secrets: Inline secrets and Key Vault references are resolved and injected into containers as environment variables or secret volume mounts.
- Private registries: Registry credentials with a password secret reference are used to pull images, including images hosted in the emulated Azure Container Registry.
- Health probes: Liveness, readiness, and startup probes (HTTP and TCP) are enforced by the local cluster.
- Container logs:
az containerapp logs showstreams logs directly from the running container via each replica’s log stream endpoint. - Jobs: Manually started job executions run to completion and report
SucceededorFailed; parallelism and replica completion count are honored. - Auxiliary resources: Dapr components, environment storages, managed certificates, and HTTP route configs support full CRUD with validation. HTTP route configs perform real path-based routing, including exact and prefix matches and prefix rewrites.
Limitations
Section titled “Limitations”- No autoscaling: KEDA scale rules are stored and echoed back but not evaluated, and scale-to-zero is not supported. Apps run with a fixed replica count derived from
minReplicas(at least 1, capped bymaxReplicas). - No traffic splitting: Traffic weights across revisions are stored but not enforced at the data plane; the latest ready revision serves all requests.
- No automatic job triggers: Scheduled (cron) and event-driven job triggers are stored but never fire;
az containerapp job startis the only way to create an execution. - Azure Files storages are metadata-only: Environment storages can be managed via CRUD, but
AzureFileandNfsAzureFilevolumes are skipped at deploy time and the container starts without the mount. - No Dapr sidecar: Dapr components and app-level Dapr configuration are stored and validated, but no Dapr sidecar is injected into running containers.
- No real certificates or domain validation: Managed certificates skip certificate issuance and DNS validation, custom domains are stored without verification, and custom hostname analysis always reports the domain verification as failed.
- No interactive log streaming or exec:
az containerapp logs show --follow, system logs (--type system), andaz containerapp execare not supported.
Samples
Section titled “Samples”API Coverage
Section titled “API Coverage”| Operation ▲ | Implemented ▼ |
|---|