Skip to content

Deployment Workflows

This guide summarizes practical deployment workflows for Azure Container Apps across CLI, Infrastructure as Code, and CI/CD pipelines.

Prerequisites

  • Azure CLI with containerapp extension installed
  • An existing Container Apps environment ($ACA_ENV_NAME)
  • An Azure Container Registry ($ACR_NAME) for image-based deployments

When to Use

Scenario Recommended Method
Fast iteration in dev/test az containerapp up --source or --artifact
Production baseline with governance Bicep / ARM templates
Team-wide standard releases CI/CD pipeline (GitHub Actions)
Emergency hotfix Direct CLI az containerapp update --image

Deployment Methods

Azure Container Apps supports four deployment methods:

flowchart LR
    subgraph "Source-Based"
        A[Source Code<br/>--source] --> B[Cloud Build]
        C[Artifact<br/>--artifact] --> B
    end
    subgraph "Image-Based"
        D[Container Image<br/>--image] --> E[Pull from Registry]
    end
    subgraph "IaC"
        F[Bicep / ARM] --> G[Declarative Deploy]
    end
    B --> H[New Revision]
    E --> H
    G --> H

Source Code Deployment

Deploy directly from source code without building a container image locally. Azure builds the image in the cloud using Oryx or a Buildpack.

az containerapp up \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --environment "$ACA_ENV_NAME" \
  --source "./apps/python"
Command Why it is used
az containerapp up ... Runs the Azure CLI operation required by the documented step.

When to use source deploy

Best for rapid prototyping and development. The platform auto-detects the language runtime and builds the image for you.

Artifact Deployment (JAR / WAR)

Deploy Java artifacts directly without writing a Dockerfile. The platform builds a container image from the artifact automatically.

az containerapp up \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --environment "$ACA_ENV_NAME" \
  --artifact "./target/myapp.jar"
Command Why it is used
az containerapp up --artifact Deploys a Java artifact (JAR/WAR) without requiring a Dockerfile.

Supported artifact types:

Artifact Extension Runtime
JAR .jar Java (Spring Boot, Quarkus, etc.)
WAR .war Java (Servlet-based)

Artifact deploy limitations

Artifact deployment is for Java applications only. For other languages, use --source or build a container image.

Container Image Deployment

The standard production deployment method. Build and push an image to a registry, then deploy.

# Build and push to ACR with an immutable tag
IMAGE_TAG="$(date +%Y%m%d%H%M%S)"
az acr build \
  --registry "$ACR_NAME" \
  --image "$APP_NAME:$IMAGE_TAG" \
  --file "apps/python/Dockerfile" \
  "apps/python"

# Deploy or update with the new image
az containerapp update \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --image "$ACR_NAME.azurecr.io/$APP_NAME:$IMAGE_TAG"
Command Why it is used
az containerapp update ... Updates the existing Container App configuration without recreating the app.

Prefer immutable tags for release traceability, and maintain a stable alias tag only for non-production testing.

Bicep / ARM Deployment

IaC deployments keep environment, identity, and app configuration consistent.

az deployment group create \
  --resource-group "$RG" \
  --template-file "infra/main.bicep" \
  --parameters "baseName=myapp" "location=$LOCATION"
Command Why it is used
az deployment group create ... Deploys the Bicep or ARM template into the target resource group.

Use what-if before production applies:

az deployment group what-if \
  --resource-group "$RG" \
  --template-file "infra/main.bicep" \
  --parameters "baseName=myapp" "location=$LOCATION"
Command Why it is used
az deployment group what-if ... Previews resource changes before deployment.

Run what-if before production IaC applies

az deployment group what-if should be mandatory for production environments to prevent accidental networking, identity, or ingress drift.

CI/CD with GitHub Actions

Use GitHub Actions to build images, push to ACR, and deploy to Container Apps in one pipeline.

Typical stages:

  1. Lint and test application code.
  2. Build container image.
  3. Push image to ACR.
  4. Deploy or update Container App / Job.
  5. Verify health endpoint and revision state.

Use workload identity federation where possible to avoid long-lived service principal secrets.

Revision Behavior and Zero-Downtime Deployments

Every deployment that changes revision-scope properties creates a new revision. In single-revision mode, the platform automatically performs a zero-downtime cutover to the new revision. In multiple-revision mode, you must explicitly manage traffic routing between revisions.

Revision-Scope vs Application-Scope Changes

Scope Creates New Revision? Examples
Revision-scope Yes Container image, environment variables, resources (CPU/memory), scale rules, probes
Application-scope No Traffic splitting, custom domains, authentication, managed identity

Traffic Splitting for Progressive Rollout

# Send 20% traffic to new revision for canary testing
az containerapp ingress traffic set \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --revision-weight "$APP_NAME--new-rev=20" "$APP_NAME--stable-rev=80"
Command Why it is used
az containerapp ingress traffic set Splits traffic between revisions by percentage for progressive rollout.

Deployment Labels (Preview)

Deployment labels allow you to route traffic to a specific revision by a stable label name, independent of revision name.

# Assign a label to a specific revision
az containerapp revision label add \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --label "canary" \
  --revision "$APP_NAME--new-rev"
Command Why it is used
az containerapp revision label add Assigns a named label to a specific revision for dedicated URL routing.

The labeled revision becomes accessible at <label>.<app-fqdn> for testing before promoting traffic.

Rollback Procedures

Quick Rollback via Traffic Shift

Route 100% traffic back to the previous stable revision:

az containerapp ingress traffic set \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --revision-weight "$APP_NAME--stable-rev=100"
Command Why it is used
az containerapp ingress traffic set Routes 100% traffic back to the stable revision for quick rollback.

Reactivate a Deactivated Revision

If the previous revision has been deactivated, reactivate it first:

az containerapp revision activate \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --revision "$APP_NAME--stable-rev"
Command Why it is used
az containerapp revision activate Reactivates a previously deactivated revision so it can receive traffic.

Redeploy a Known-Good Image

az containerapp update \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --image "$ACR_NAME.azurecr.io/$APP_NAME:last-known-good"
Command Why it is used
az containerapp update --image Redeploys the app with a known-good image tag to create a new stable revision.

Inactive Revision Cleanup

Old revisions consume no compute but remain listed. Limit inactive revisions to reduce clutter:

az containerapp update \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --max-inactive-revisions 5
Command Why it is used
az containerapp update --max-inactive-revisions Sets the maximum number of inactive revisions to retain.

Revision cleanup

Setting --max-inactive-revisions automatically purges the oldest inactive revisions when the count exceeds the limit. This does not affect active revisions receiving traffic.

Deployment Workflow and Release Guardrails

flowchart TD
    A[Commit Merged] --> B[Build and Test]
    B --> C[Push Immutable Image to ACR]
    C --> D[Deploy New Revision]
    D --> E[Run Health and SLO Checks]
    E --> F{Healthy?}
    F -->|Yes| G[Promote Traffic]
    F -->|No| H[Rollback Traffic]
    H --> I[Open Incident and Fix]
Deployment Method Strength Tradeoff Best Operational Use
Source deploy (--source) No Dockerfile needed Less control over build Prototyping and dev environments
Artifact deploy (--artifact) No Dockerfile for Java Java-only Java apps without container expertise
Direct CLI (az containerapp update --image) Fastest change path Higher drift risk Hotfixes and smoke deployments
Bicep (az deployment group create) Deterministic infra state Requires template discipline Production baseline and governance
CI/CD pipeline Approval + traceability + repeatability More setup overhead Team-wide standard release workflow

Prefer immutable image tags per deployment

Use tags like git-<sha> or date-based release tags to guarantee revision traceability and safe rollback.

Deployment Checklist

  • Container image built from pinned base image and scanned.
  • Revision mode and traffic strategy validated.
  • Health probes configured and verified.
  • Managed identity and secret references resolved.
  • Post-deploy smoke test completed.
  • Rollback path documented and tested.

Progressive Rollout Example

export IMAGE_TAG="git-$(git rev-parse --short HEAD)"
export IMAGE_NAME="$ACR_NAME.azurecr.io/$APP_NAME:$IMAGE_TAG"

az acr build \
  --registry "$ACR_NAME" \
  --image "$APP_NAME:$IMAGE_TAG" \
  --file "apps/python/Dockerfile" \
  "apps/python"

az containerapp update \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --image "$IMAGE_NAME"

az containerapp revision list \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --output table
Command Why it is used
az acr build ... Builds and pushes the container image to Azure Container Registry.

Post-Deployment Acceptance Checks

az containerapp logs show \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --type console \
  --follow false

az containerapp ingress traffic show \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --output table
Command Why it is used
az containerapp logs show ... Runs the Azure CLI operation required by the documented step.

See Also

Sources