Azure Container Apps: The Complete Guide

Azure Container Apps: The Complete Guide

Markus Lehmann ยท January 08, 2026
AzureContainer AppsDeployment
Docker.NET

Azure Container Apps (ACA) has become my go-to platform for deploying .NET microservices. It offers the right balance between simplicity and control: you get container orchestration without managing Kubernetes directly. Here's everything I've learned from running production workloads on the platform.

What Azure Container Apps Offers

ACA sits between Azure App Service and Azure Kubernetes Service. You get container-based deployments with built-in scaling, ingress, secrets management, and Dapr integration, without writing YAML manifests or managing cluster nodes.

Key features:

  • HTTP and event-driven scaling from zero to many replicas
  • Built-in ingress with HTTPS termination and custom domains
  • Revision management for blue-green and canary deployments
  • Managed identity for secure access to other Azure resources
  • Dapr sidecar for service-to-service communication (optional)

Deploying a .NET Application

The fastest path from code to ACA is the Azure Developer CLI (azd):

azd init
azd up

For more control, use the Azure CLI directly:

# Create the environment
az containerapp env create \
  --name my-env \
  --resource-group my-rg \
  --location westeurope

# Deploy from a container image
az containerapp create \
  --name my-api \
  --resource-group my-rg \
  --environment my-env \
  --image myregistry.azurecr.io/my-api:latest \
  --target-port 8080 \
  --ingress external \
  --min-replicas 1 \
  --max-replicas 5 \
  --cpu 0.5 \
  --memory 1Gi

Scaling Configuration

ACA supports multiple scaling triggers. The most common for web APIs is HTTP-based scaling:

az containerapp update \
  --name my-api \
  --resource-group my-rg \
  --scale-rule-name http-scaling \
  --scale-rule-type http \
  --scale-rule-http-concurrency 50 \
  --min-replicas 1 \
  --max-replicas 10

This scales up when concurrent requests per replica exceed 50. For background workers, you can scale on queue length, custom metrics, or KEDA-supported event sources.

Scaling to zero is supported and eliminates costs during idle periods, but adds cold-start latency. For production APIs, I recommend setting min-replicas to at least 1.

Secrets and Configuration

ACA has a built-in secrets store, but I prefer using Azure Key Vault with managed identity for production:

# Enable managed identity
az containerapp identity assign \
  --name my-api \
  --resource-group my-rg \
  --system-assigned

# Reference Key Vault secrets
az containerapp update \
  --name my-api \
  --resource-group my-rg \
  --set-env-vars \
    "ConnectionStrings__Database=secretref:db-connection-string"

In your .NET code, the Key Vault configuration provider loads secrets transparently:

builder.Configuration.AddAzureKeyVault(
    new Uri(builder.Configuration["KeyVault:Url"]!),
    new DefaultAzureCredential());

Health Probes

Configure liveness and readiness probes to ensure ACA routes traffic correctly:

{
  "probes": [
    {
      "type": "liveness",
      "httpGet": {
        "path": "/alive",
        "port": 8080
      },
      "periodSeconds": 10
    },
    {
      "type": "readiness",
      "httpGet": {
        "path": "/health",
        "port": 8080
      },
      "periodSeconds": 5
    }
  ]
}

ASP.NET Core's health check middleware maps naturally to these probes. The readiness probe should verify database connectivity, while the liveness probe should be a simple check that the process is running.

Multi-Service Architecture

For applications with multiple services, use an ACA environment to group them. Services within the same environment can communicate via internal ingress:

# Internal service (not publicly accessible)
az containerapp create \
  --name my-worker \
  --environment my-env \
  --ingress internal \
  --target-port 8080

Services discover each other by name within the environment. The URL pattern is https://my-worker.internal.<env-domain>.

.NET Aspire Integration

If you're using .NET Aspire, deployment to ACA is nearly automatic. The Aspire AppHost generates the required Bicep templates:

azd init
azd up

Aspire maps each project and container resource to an ACA instance, configures service discovery, provisions databases and caches, and wires up monitoring through Application Insights. This is by far the smoothest deployment experience I've used for .NET distributed applications.

Cost Optimization Tips

ACA uses a consumption-based pricing model. To control costs:

  • Set max-replicas based on actual load testing, not theoretical maximums
  • Use scale-to-zero for development and staging environments
  • Choose the right CPU and memory allocation; over-provisioning wastes money
  • Monitor with Azure Cost Management and set budget alerts

Azure Container Apps strikes the right balance for most .NET workloads. You get the benefits of containerization without the operational complexity of Kubernetes, and the integration with the .NET ecosystem continues to improve with each release.


Comments (2)

Elena Mar 03, 2026 · 17:08

I tried this approach and it works perfectly!

Greta Feb 19, 2026 · 20:08

I had the same experience, can confirm.

Felix Mar 04, 2026 · 17:08

Well written and easy to follow. Keep it up!


Leave a comment

An unhandled error has occurred. Reload ๐Ÿ—™

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.