Claude-skill-registry azure-container-apps

Deploy containerized apps with Azure Container Apps. Configure auto-scaling, Dapr integration, traffic splitting, and managed identities. Use for microservices, APIs, background jobs, and event-driven applications on Azure.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/azure-container-apps" ~/.claude/skills/majiayu000-claude-skill-registry-azure-container-apps && rm -rf "$T"
manifest: skills/data/azure-container-apps/SKILL.md
source content

Azure Container Apps

Expert guidance for serverless containers on Azure.

CLI Setup

# Install extension
az extension add --name containerapp --upgrade

# Register providers
az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

Create Environment

# Create resource group
az group create --name myResourceGroup --location eastus

# Create Container Apps environment
az containerapp env create \
  --name myEnvironment \
  --resource-group myResourceGroup \
  --location eastus

Deploy Container App

From Image

az containerapp create \
  --name myapp \
  --resource-group myResourceGroup \
  --environment myEnvironment \
  --image mcr.microsoft.com/azuredocs/containerapps-helloworld:latest \
  --target-port 80 \
  --ingress external \
  --min-replicas 1 \
  --max-replicas 10 \
  --cpu 0.5 \
  --memory 1Gi

From Source Code

az containerapp up \
  --name myapp \
  --resource-group myResourceGroup \
  --environment myEnvironment \
  --source . \
  --ingress external \
  --target-port 8080

YAML Configuration

# containerapp.yaml
properties:
  managedEnvironmentId: /subscriptions/.../managedEnvironments/myEnvironment
  configuration:
    ingress:
      external: true
      targetPort: 8080
      transport: http
      traffic:
        - weight: 100
          latestRevision: true
    registries:
      - server: myregistry.azurecr.io
        identity: system
    secrets:
      - name: db-connection
        value: "Server=..."
  template:
    containers:
      - name: myapp
        image: myregistry.azurecr.io/myapp:latest
        resources:
          cpu: 0.5
          memory: 1Gi
        env:
          - name: DATABASE_URL
            secretRef: db-connection
          - name: ENVIRONMENT
            value: production
        probes:
          - type: Liveness
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          - type: Readiness
            httpGet:
              path: /ready
              port: 8080
    scale:
      minReplicas: 1
      maxReplicas: 30
      rules:
        - name: http-scaling
          http:
            metadata:
              concurrentRequests: "100"

Scaling Rules

HTTP Scaling

scale:
  minReplicas: 0
  maxReplicas: 100
  rules:
    - name: http-rule
      http:
        metadata:
          concurrentRequests: "50"

Queue-based Scaling (Azure Queue)

scale:
  minReplicas: 0
  maxReplicas: 30
  rules:
    - name: queue-rule
      azureQueue:
        queueName: myqueue
        queueLength: 10
        auth:
          - secretRef: queue-connection
            triggerParameter: connection

Custom Metrics (KEDA)

scale:
  minReplicas: 0
  maxReplicas: 50
  rules:
    - name: kafka-rule
      custom:
        type: kafka
        metadata:
          bootstrapServers: kafka:9092
          consumerGroup: mygroup
          topic: mytopic
          lagThreshold: "100"

Dapr Integration

Enable Dapr

properties:
  configuration:
    dapr:
      enabled: true
      appId: myapp
      appPort: 8080
      appProtocol: http

Dapr Components

# pubsub.yaml
componentType: pubsub.azure.servicebus
metadata:
  - name: connectionString
    secretRef: servicebus-connection
secrets:
  - name: servicebus-connection
    value: "Endpoint=sb://..."
scopes:
  - myapp
  - worker

Traffic Splitting

# Create new revision
az containerapp update \
  --name myapp \
  --resource-group myResourceGroup \
  --image myapp:v2 \
  --revision-suffix v2

# Split traffic
az containerapp ingress traffic set \
  --name myapp \
  --resource-group myResourceGroup \
  --revision-weight myapp--v1=80 myapp--v2=20

Jobs

Scheduled Job

az containerapp job create \
  --name myjob \
  --resource-group myResourceGroup \
  --environment myEnvironment \
  --trigger-type Schedule \
  --cron-expression "0 */6 * * *" \
  --image myregistry.azurecr.io/myjob:latest \
  --cpu 0.5 \
  --memory 1Gi \
  --replica-timeout 1800 \
  --replica-retry-limit 3

Event-driven Job

properties:
  configuration:
    triggerType: Event
    replicaTimeout: 1800
    eventTriggerConfig:
      scale:
        minExecutions: 0
        maxExecutions: 10
        rules:
          - name: queue-trigger
            type: azure-queue
            metadata:
              queueName: jobs
              queueLength: "1"

Bicep Deployment

resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
  name: appName
  location: location
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    managedEnvironmentId: environment.id
    configuration: {
      ingress: {
        external: true
        targetPort: 8080
        transport: 'http'
        corsPolicy: {
          allowedOrigins: ['https://myapp.com']
          allowedMethods: ['GET', 'POST']
        }
      }
      secrets: [
        {
          name: 'registry-password'
          value: containerRegistry.listCredentials().passwords[0].value
        }
      ]
      registries: [
        {
          server: '${containerRegistry.name}.azurecr.io'
          username: containerRegistry.name
          passwordSecretRef: 'registry-password'
        }
      ]
    }
    template: {
      containers: [
        {
          name: appName
          image: '${containerRegistry.name}.azurecr.io/${appName}:${imageTag}'
          resources: {
            cpu: json('0.5')
            memory: '1Gi'
          }
          env: [
            {
              name: 'ASPNETCORE_ENVIRONMENT'
              value: 'Production'
            }
          ]
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 10
        rules: [
          {
            name: 'http-scale'
            http: {
              metadata: {
                concurrentRequests: '100'
              }
            }
          }
        ]
      }
    }
  }
}

Managed Identity

# Enable system-assigned identity
az containerapp identity assign \
  --name myapp \
  --resource-group myResourceGroup \
  --system-assigned

# Grant access to Key Vault
az keyvault set-policy \
  --name mykeyvault \
  --object-id <identity-principal-id> \
  --secret-permissions get list

Monitoring

# View logs
az containerapp logs show \
  --name myapp \
  --resource-group myResourceGroup \
  --type console

# Stream logs
az containerapp logs show \
  --name myapp \
  --resource-group myResourceGroup \
  --follow

# View system logs
az containerapp logs show \
  --name myapp \
  --resource-group myResourceGroup \
  --type system

Resources