Notice: Function WP_Scripts::add was called incorrectly. The script with the handle "markdown-renderer" was enqueued with dependencies that are not registered: mermaid-js, prism-core. Please see Debugging in WordPress for more information. (This message was added in version 6.9.1.) in /home/dataadl/www/wp-includes/functions.php on line 6131

Azure Container Apps: Complete Production Deployment Guide

Azure Container Apps (ACA) represents Microsoft’s vision for a serverless container platform that sits between Azure Functions and Azure Kubernetes Service in complexity. Now Generally Available, ACA provides a fully managed environment for deploying containerized applications with built-in support for KEDA autoscaling, Dapr integration, and seamless CI/CD. Having deployed multiple production workloads on ACA, this guide shares everything you need to know for enterprise adoption.

Architectural Overview

Azure Container Apps runs on an AKS foundation but abstracts away all Kubernetes complexity. You never interact with Deployments, Services, or Ingress resources. Instead, you work with Container Apps, Environments, and Revisions.

flowchart TB
    subgraph Environment ["Container Apps Environment"]
        subgraph VNET ["Virtual Network"]
            App1["Container App: API"]
            App2["Container App: Worker"]
            App3["Container App: Frontend"]
            
            App1 -- Dapr --> App2
            App3 --> App1
        end
        
        Ingress["Managed Ingress (Envoy)"]
        KEDA["KEDA Autoscaler"]
        Dapr["Dapr Sidecar Runtime"]
    end
    
    Users["Internet Users"] --> Ingress
    Ingress --> App3
    
    style Environment fill:#E1F5FE,stroke:#0277BD
    style KEDA fill:#C8E6C9,stroke:#2E7D32

Creating a Container Apps Environment

The Environment is the isolation boundary. All apps within an environment share the same virtual network and logging configuration:

param location string = resourceGroup().location
param environmentName string = 'myapp-env'

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: '${environmentName}-logs'
  location: location
  properties: {
    sku: { name: 'PerGB2018' }
    retentionInDays: 30
  }
}

resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2022-10-01' = {
  name: environmentName
  location: location
  properties: {
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalytics.properties.customerId
        sharedKey: logAnalytics.listKeys().primarySharedKey
      }
    }
    vnetConfiguration: {
      internal: false
      infrastructureSubnetId: vnet::infraSubnet.id
    }
    zoneRedundant: true // Enable for production workloads
  }
}

Deploying a Container App

Here is a complete example of deploying a .NET 6 API with autoscaling, secrets, and managed identity:

resource containerApp 'Microsoft.App/containerApps@2022-10-01' = {
  name: 'order-api'
  location: location
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    managedEnvironmentId: containerAppsEnvironment.id
    configuration: {
      activeRevisionsMode: 'Multiple' // Blue-green deployments
      ingress: {
        external: true
        targetPort: 80
        transport: 'http'
        traffic: [
          { revisionName: 'order-api--v1', weight: 90 }
          { revisionName: 'order-api--v2', weight: 10 }
        ]
      }
      secrets: [
        {
          name: 'db-connection-string'
          keyVaultUrl: 'https://myvault.vault.azure.net/secrets/DbConnectionString'
          identity: 'system'
        }
      ]
      registries: [
        {
          server: 'myacr.azurecr.io'
          identity: 'system'
        }
      ]
    }
    template: {
      containers: [
        {
          name: 'api'
          image: 'myacr.azurecr.io/order-api:v1.2.0'
          resources: {
            cpu: json('0.5')
            memory: '1Gi'
          }
          env: [
            { name: 'ASPNETCORE_ENVIRONMENT', value: 'Production' }
            { name: 'ConnectionStrings__Database', secretRef: 'db-connection-string' }
          ]
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 30
        rules: [
          {
            name: 'http-scaling'
            http: {
              metadata: {
                concurrentRequests: '100'
              }
            }
          }
          {
            name: 'queue-scaling'
            custom: {
              type: 'azure-queue'
              metadata: {
                queueName: 'orders'
                queueLength: '10'
                accountName: 'mystorageaccount'
              }
              auth: [
                { secretRef: 'storage-connection', triggerParameter: 'connection' }
              ]
            }
          }
        ]
      }
    }
  }
}

Dapr Integration

ACA has first-class Dapr support. Enable it to get service-to-service invocation, state management, and pub/sub without changing your code:

# component.yaml - Azure Service Bus pub/sub
componentType: pubsub.azure.servicebus.topics
version: v1
metadata:
  - name: connectionString
    secretRef: servicebus-connection
  - name: consumerID
    value: order-processor
// Your code - no SDK references, just HTTP
await daprClient.PublishEventAsync("pubsub", "orders", orderData);

// Receiving side
[HttpPost("/orders")]
public async Task HandleOrder([FromBody] CloudEvent<Order> order)
{
    // Process order
}

Blue-Green Deployments

ACA’s revision management makes blue-green deployments trivial:

# Deploy new revision
az containerapp update -n order-api -g mygroup \
  --image myacr.azurecr.io/order-api:v1.3.0

# Route 10% traffic to new revision
az containerapp ingress traffic set -n order-api -g mygroup \
  --revision-weight order-api--v12=90 order-api--v13=10

# If healthy, shift all traffic
az containerapp ingress traffic set -n order-api -g mygroup \
  --revision-weight order-api--v13=100

Networking and Security

For production workloads, deploy into a VNET with private ingress:

  • Internal Ingress: Apps only accessible within VNET
  • Private Endpoints: Connect to Azure SQL, Cosmos DB without public IPs
  • NSGs: Control traffic flow between subnets
  • Managed Identity: Authenticate to Azure services without secrets

Key Takeaways

  • ACA is ideal for microservices that don’t need raw Kubernetes access
  • Enable Zone Redundancy for production workloads
  • Use Managed Identity for zero-secret deployments
  • Leverage KEDA scalers for queue-based workloads
  • Dapr integration simplifies service mesh patterns
  • Traffic splitting enables safe blue-green deployments

Discover more from C4: Container, Code, Cloud & Context

Subscribe to get the latest posts sent to your email.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.