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
containerappextension 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:
- Lint and test application code.
- Build container image.
- Push image to ACR.
- Deploy or update Container App / Job.
- 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:
| 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¶
- Deploy with the Azure Developer CLI (azd)
- Deployment (Platform)
- Revision Strategy (Best Practices)
- Revisions (Platform)
- Language Guides
- Revision Management
- Recovery and Incident Readiness