What is a Container App?

Azure Container Apps is a serverless platform for running containerized applications on Microsoft Azure. You hand it a container image, tell it how to listen for traffic, and the platform handles the rest - the compute it runs on, the HTTPS endpoint in front of it, the certificates, the scaling, and the rolling updates when a new version ships.

It is built on top of Kubernetes, but you never see the cluster. There are no nodes to size, no kubectl contexts to keep straight, no control plane to patch. The unit you work with is the app: a container image plus a small bundle of configuration that tells the platform how to run it, scale it, and route traffic to it.

Azure Container Apps is a fully managed serverless container service that enables you to deploy and run containerized applications.- Microsoft Learn

The problem it solves

For most teams, the choice on Azure used to be uncomfortable. If your workload fit a function - small, stateless, per-event - Azure Functions was the obvious answer. If your workload looked like a real service, you ended up on Azure Kubernetes Service, and inherited a cluster to operate.

Container Apps sits in the middle. It is built for the workloads that are too long-lived or too "real" to fit into a function, but do not need - and do not want - the operational weight of a full Kubernetes cluster. APIs, background workers, queue consumers, gRPC services, Dapr microservices, internal admin tools: containerized applications that just need a managed place to run.

The pitch is straightforward. You bring the container. Azure brings the platform.

The environment

Container Apps are not deployed in isolation - they live inside a Container Apps environment. The environment is the boundary the platform manages: a virtual network, a log destination, a set of shared infrastructure for the apps inside it.

Several apps in the same environment share networking, secrets references, Dapr components, and observability. They can call each other on stable internal DNS names, route traffic across each other, and emit logs and metrics to the same destination. From the outside, the environment is the unit of isolation; from the inside, it is the unit of cohesion.

In practice you create one environment per application or per environment tier (dev, staging, prod) and deploy every related service - the API, the worker, the scheduled job - into it.

Anatomy of an app

Behind the CLI is a typed Azure resource - the same one you'd author in Bicep, Terraform, or ARM. Here is roughly what the API above looks like as a resource definition:

YAML api.yaml
properties: environmentId: /subscriptions/.../managedEnvironments/my-env configuration: ingress: external: true targetPort: 8080 # the port your container listens on transport: auto secrets: - name: db-connection keyVaultUrl: "https://kv.../secrets/db" template: containers: - name: api image: myreg.azurecr.io/api:v3 resources: cpu: 0.5 memory: "1Gi" env: - name: DB secretRef: db-connection scale: minReplicas: 0 maxReplicas: 10 rules: - name: http-rule http: metadata: { concurrentRequests: "50" }

Two halves do most of the work. Configuration describes how the app is exposed to the outside world - ingress, secrets, registries, Dapr - and is stable across deployments. Template describes what runs inside - the container image, the resources, the environment variables, the scale rules - and is the part you change when you ship a new version. Updating template creates a new revision; updating configuration does not.

Scale to zero (and back)

The most distinctive thing about Container Apps is that it can scale your app all the way down to zero replicas when nothing is happening, and back up when traffic returns. You pay only while replicas are running, billed per vCPU-second and GiB-second; an idle app costs effectively nothing.

Scaling is driven by KEDA - an open-source autoscaler embedded in the platform. The built-in HTTP scaler counts concurrent requests per replica; if requests pile up, the platform adds replicas until they're handled. When the app is quiet, replicas drop away.

You are not limited to HTTP, though. The same scale rule block accepts any KEDA scaler - Service Bus queues, Storage Queues, Event Hubs, Kafka, Redis, CPU, memory, or a generic external source. A worker that processes messages from Service Bus can scale on queue depth; a CPU-bound service can scale on load. The scale rule is the contract; the metric source plugs in behind it.

One caveat worth knowing up front. Scaling from zero is not instant - the platform has to start a replica, which means pulling the image (if it isn't cached) and waiting for the container to boot. If every request matters, set minReplicas: 1 and keep one replica warm. Otherwise zero is a real option.

Revisions and traffic

Every meaningful change to an app produces a revision - an immutable snapshot of the template at that moment in time. The platform can keep multiple revisions of the same app alive at once, and lets you split incoming traffic between them by percentage.

That is what makes blue-green and canary deployments first-class. Ship a new revision at 0%, smoke-test it on its own dedicated URL, then move 10% of production traffic over and watch the metrics. If something looks off, drop it back to 0% in a single command. If it looks good, take it to 100% and deactivate the previous revision. No load balancer to wrangle, no DNS to swap.

Most teams run their app in single revision mode by default - the latest revision gets all the traffic - and switch to multiple revisions mode only when they need to split it. The choice is per-app and changeable at any time.

What you get for free

The reason Container Apps is worth choosing is not any one feature - it is the pile of things you do not have to build yourself. Out of the box, every app gets:

INGRESS

HTTPS, managed

External or internal endpoint with a free *.azurecontainerapps.io hostname, managed TLS certificate, and HTTP/2 + WebSockets support.

SCALE

To zero

KEDA-driven autoscaling on HTTP concurrency, queue depth, CPU, or any supported scaler. No idle bill when nothing is happening.

REVISIONS

Built in

Immutable revisions per template change, per-revision URLs for smoke testing, and traffic splitting for blue-green and canary releases.

IDENTITY

Managed by Azure

System or user-assigned managed identity attached to the app, so it can pull from ACR and call Azure services without storing credentials.

DAPR

First class

Optional Dapr sidecar with state stores, pub/sub, secrets, and service invocation - the microservices runtime, wired in by configuration.

OBSERVABILITY

Wired up

Container logs streamed to Log Analytics, system metrics in Azure Monitor, and live log tail from the CLI - no agents to install.

None of these are checkboxes you have to flip - they come standard. The work of running a containerized service in production is already in the box.

Where it sits in Azure

Azure has more than one place to run code, and they overlap. The simplest way to keep them straight is to think about the shape of the workload and how much of the runtime you want to own.

Azure Functions

Short, per-event code. Fastest to start, billed per execution, capped at a few minutes on the consumption plan. Pick when the work is function-shaped and finishes in seconds.

Container Instances

A single container with no orchestration - no scaling, no rolling updates, no environment. The right primitive when you want one container and nothing more, or when something else is wrapping it.

Container Apps

Serverless containers as long-lived services. KEDA scaling, revisions, ingress, managed identity, Dapr - on a shared environment. The sweet spot for containerized services that don't need a cluster.

Kubernetes (AKS)

Full Kubernetes - every knob, every plugin, every responsibility. Pick when you need primitives Container Apps does not expose, or when you already run a cluster and the workload belongs there.

Container Apps is not the most powerful option in that list, and it is not the cheapest at the per-event end either. It is the option that gives you the most platform for the least operational weight, for the shape of workload that lives in the middle.

When to reach for it

Container Apps earns its place when you have a containerized service and want a managed home for it without becoming a Kubernetes operator. Specifically:

  • An HTTP or gRPC API that needs HTTPS, autoscaling, and rolling deployments, without you wiring up a load balancer and certificates by hand.
  • A queue-driven worker that should scale up when messages arrive on Service Bus, Storage Queue, or Event Hubs - and scale to zero when the queue is empty.
  • A set of microservices that talk to each other and want shared networking, observability, and Dapr building blocks without the AKS operational surface.
  • An Aspire stack that models a distributed app in code and deploys the whole topology - services, jobs, and infrastructure - to a Container Apps environment as the runtime.

For work that is task-shaped instead of service-shaped - a nightly report, a backup, a one-off migration - the same platform offers Container Apps Jobs, sharing the environment with the services next to them. If you are deciding between the two for a particular workload, Container App vs Container App Job walks through the dividing line and a four-question decision tree.

SHIP

The image

You bring a container. The platform brings the compute, the networking, the certificates, and the scale.

SCALE

To zero

KEDA-driven autoscaling on HTTP, queues, CPU, or any supported source. No idle bill when nothing is happening.

RELEASE

By revision

Immutable revisions and percentage-based traffic splitting make blue-green and canary releases first-class.

NO

Cluster to run

Built on Kubernetes, but you never see it. No nodes, no kubectl, no control plane - just the app you're shipping.