Fix Azure Container Apps: Setup, Config & Deployment Errors

Microsoft Fix Intermediate 18 min read Official Docs Grounded Updated April 20, 2026

Why This Is Happening

Here's a scenario I see constantly: you've built a containerized app that runs perfectly on your laptop. Docker up, everything green. You push it to Azure Container Apps and… nothing. The container just crashes. Or it starts but you can't reach it. Or your environment variables are missing at runtime even though you set them. The Azure portal shows a vague "Provisioning failed" message and you're left staring at it wondering what went wrong.

I know this is frustrating , especially when it blocks a deadline. Azure Container Apps is genuinely great once it's working, but the gap between "it works locally" and "it works in production" is where most people get stuck. That gap isn't random either. There are very specific, repeatable reasons why Azure Container Apps deployments fail, and once you understand them you can fix them fast.

Azure Container Apps is a serverless container platform. It handles scaling, security, infrastructure management, and deployment, you're not supposed to think about the underlying servers. But that abstraction also means when something goes wrong, the error messages are often one level removed from the real cause. The platform is managing Kubernetes, Dapr, KEDA, and your custom container all at once, so a misconfiguration in any one of those layers bubbles up as a generic "container failed to start" message in your portal.

The most common root causes I've tracked across dozens of real deployments fall into five buckets:

  • Container image access problems, the environment can't pull your image from the registry, especially when using private registries or Azure Container Registry with misconfigured managed identity permissions.
  • Ingress misconfiguration, your app is running but unreachable because HTTP or TCP ingress wasn't enabled, or the target port doesn't match what your app actually listens on.
  • Scaling rules set to zero when they shouldn't be, applications that scale on CPU or memory load cannot scale to zero, but this is a common misconfiguration that leaves apps perpetually unavailable.
  • Secret and environment variable errors, secrets referenced in environment variables but not actually defined in the container app's secret store, causing startup failures at runtime.
  • Resource quota limits, hitting environment-level CPU and memory quotas that silently prevent new revisions from provisioning.

The good news: every single one of these has a clear, documented fix. Let's work through them systematically. Browse all Microsoft fix guides →

The Quick Fix, Try This First

Before you go deep on troubleshooting, run this Azure CLI command to pull the real logs from your container. The portal view is often too high-level to be useful. This command gives you the actual stdout/stderr from inside your container, which is almost always where the real error lives:

az containerapp logs show \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --type console \
  --follow

If you haven't installed the Container Apps CLI extension yet, add it first:

az extension add --name containerapp --upgrade

Once you see the real logs, 80% of the time the problem becomes obvious. A missing environment variable, a port mismatch, a package that failed to install, these all show up clearly in console output. The portal's "Provisioning failed" tells you nothing. The actual container logs tell you everything.

After reading the logs, check your revision status specifically. A new revision might be stuck in a "Provisioning" state indefinitely if the previous command failed silently:

az containerapp revision list \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --output table

Look at the "Active" and "Running" columns. If your newest revision shows 0 running replicas, it means the container failed to start. The traffic is still being handled by the previous revision (if one exists), which is why the issue can look invisible from the outside but your new code isn't running.

If you see the revision is inactive, deactivate and reactivate it to force a fresh pull:

az containerapp revision deactivate \
  --revision REVISION_NAME \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP

az containerapp revision activate \
  --revision REVISION_NAME \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP
Pro Tip
Always check your container image tag before assuming a code problem. If you're using :latest and your registry hasn't been re-pulled, you might be running old code. Switch to explicit version tags (e.g., myapp:1.4.2) so every deployment is deterministic, :latest is a major source of "it was working yesterday" confusion in Container Apps environments.
1
Verify Container Registry Access and Image Pull Permissions

This is the number one silent killer of Azure Container Apps deployments. Your container image might be perfectly built, but if the Container Apps environment can't pull it from the registry, the app will fail to start with no useful error in the portal.

If you're using Azure Container Registry (ACR), the cleanest fix is to enable managed identity authentication. First, get your ACR resource ID:

az acr show \
  --name YOUR_ACR_NAME \
  --query id \
  --output tsv

Then assign the AcrPull role to your container app's managed identity:

az role assignment create \
  --assignee YOUR_APP_PRINCIPAL_ID \
  --role AcrPull \
  --scope /subscriptions/YOUR_SUB/resourceGroups/YOUR_RG/providers/Microsoft.ContainerRegistry/registries/YOUR_ACR

To find your app's principal ID:

az containerapp show \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --query "identity.principalId" \
  --output tsv

If you're using Docker Hub or another private registry, you need to supply registry credentials directly during the update. Never hardcode credentials into your container image. Instead, pass them securely through the CLI:

az containerapp registry set \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --server docker.io \
  --username YOUR_DOCKERHUB_USERNAME \
  --password YOUR_DOCKERHUB_TOKEN

Use a Docker Hub access token here, not your account password. Once this is configured correctly, redeploy your revision. You should see the replica count move from 0 to 1 within about 30 seconds if the image pull was the only problem.

2
Configure Ingress Settings to Match Your App's Actual Port

Ingress is one of the most common Azure Container Apps configuration errors I see, and it's almost always a port mismatch. Your app listens on port 3000 (or 8080, or 5000), but the ingress target port is set to something different, so requests never reach your container.

In the Azure portal, navigate to your container app → SettingsIngress. Check the "Target port" field. It must match exactly what your application listens on inside the container, not an external port, not a mapped port, the internal container port.

You can also set this via CLI during deployment:

az containerapp ingress enable \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --type external \
  --target-port 3000 \
  --transport http

If your app uses HTTPS internally (not common but possible), change --transport to http2 or https as appropriate. For TCP-based applications that aren't HTTP, use --transport tcp.

Azure Container Apps lets you enable HTTPS ingress without touching any other Azure infrastructure, no load balancers to configure, no certificates to manage manually. The platform handles TLS termination for you. But you must explicitly enable ingress; it's off by default on new container apps.

Once ingress is configured correctly, test it immediately:

az containerapp show \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --query "properties.configuration.ingress.fqdn" \
  --output tsv

That command returns your app's public URL. Hit it with curl or open it in your browser. If you get a connection refused, recheck the target port. If you get a 502 Bad Gateway, your container is starting but crashing before it can serve traffic, go back to the logs from Step 1.

3
Fix Scaling Rules That Prevent Your App From Starting

Azure Container Apps can scale to zero replicas when there's no traffic, that's one of its biggest cost-saving features. But there's a hard rule you need to know: applications that scale on CPU or memory load cannot scale to zero. If you've set a CPU-based or memory-based scaling rule and also configured a minimum replica count of zero, your app may never start, or it may go to zero and never come back.

Check your current scaling configuration:

az containerapp show \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --query "properties.template.scale" \
  --output json

Look at the minReplicas and maxReplicas values, and examine each rule in the rules array. If any rule uses cpu or memory as the scale type, your minReplicas must be at least 1.

Fix it with:

az containerapp update \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --min-replicas 1 \
  --max-replicas 10

For HTTP-traffic-based scaling (the most common setup for API endpoints), scale-to-zero works fine. The platform will spin up a replica when the first request arrives, though you'll see a cold start delay of a few seconds on that first request after a period of no traffic. If cold starts are unacceptable for your workload, set --min-replicas 1 regardless of your scale trigger type.

For KEDA-supported scalers (Azure Service Bus, Event Hubs, custom metrics), always test the scaler configuration explicitly using the KEDA docs for that specific trigger. A misconfigured KEDA scaler will silently keep your replica count at zero even when there's work to do.

4
Manage Secrets and Environment Variables Correctly

This one trips up even experienced engineers. In Azure Container Apps, secrets and environment variables are two separate concepts that need to be connected explicitly. You can't just set an environment variable to a secret value inline, you need to first define the secret in the container app's secret store, then reference that secret in your environment variable definition.

Here's the correct flow. First, add your secret:

az containerapp secret set \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --secrets "db-connection-string=your-actual-connection-string-value"

Then reference that secret in an environment variable:

az containerapp update \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --set-env-vars "DB_CONNECTION_STRING=secretref:db-connection-string"

The secretref: prefix is what tells Container Apps to resolve the value from the secret store at runtime rather than storing it as a plain environment variable. If you skip this and set the value directly, it shows up in plain text in your revision configuration, visible to anyone with read access to the resource. That's a security problem worth avoiding.

A very common mistake: updating a secret value doesn't automatically restart your container. The secret is injected at startup, so your app keeps using the old value until a new revision is deployed. After changing a secret, create a new revision explicitly:

az containerapp update \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --revision-suffix v2-updated-secrets

In the portal, you can manage secrets by navigating to your container app → SettingsSecrets. Add, edit, or delete secrets there, then go to Revisions and create a new revision to pick up the changes. The UI makes this straightforward, but that manual "create revision" step is easy to miss.

5
Deploy Consistently Across Environments Using Revision Management

One of the most powerful features of Azure Container Apps is that every deployment creates a new revision, a snapshot of your container configuration at that point in time. This directly answers the question "how do I reliably deploy my application?" The answer is: use revisions deliberately, not accidentally.

By default, Container Apps uses single-revision mode, meaning each new deployment replaces the previous one. For production workloads, switch to multiple-revision mode so you can keep old revisions available for rollback:

az containerapp revision set-mode \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --mode multiple

With multiple revisions active, you can split traffic between them, which enables Blue/Green deployments and A/B testing. For example, to send 10% of traffic to a new revision while keeping 90% on the stable one:

az containerapp ingress traffic set \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --revision-weight \
    stable-revision=90 \
    new-revision=10

This is how you test a new version in production without taking on full risk. Watch your Azure Log Analytics metrics for the new revision's error rate. If it's clean, shift more traffic. If something's wrong, shift traffic back to 100% on the stable revision, no downtime, no panic.

To manage your deployment pipeline with confidence across dev, staging, and production environments, export your container app configuration as an ARM template or YAML spec and commit it to source control. Then deploy it via GitHub Actions using the azure/container-apps-deploy-action. This gives you the consistency and traceability you need to ensure "what works in staging works in production."

az containerapp show \
  --name YOUR_APP_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --output yaml > containerapp-config.yaml

Commit that YAML file. When something breaks in production, you have a diff-able history of every configuration change. That's worth more than most monitoring tools.

Advanced Troubleshooting

Diagnosing Failures with Azure Log Analytics

When the CLI logs aren't enough, go deeper with Azure Log Analytics. Every Container Apps environment is connected to a Log Analytics workspace by default. Open the Azure portal, navigate to your Log Analytics workspace (find it via your Container Apps environment → MonitoringLogs), and run Kusto queries against the ContainerAppConsoleLogs_CL table.

This query surfaces all errors from your app in the last hour:

ContainerAppConsoleLogs_CL
| where TimeGenerated > ago(1h)
| where ContainerAppName_s == "YOUR_APP_NAME"
| where Log_s contains "error" or Log_s contains "Error" or Log_s contains "ERROR"
| project TimeGenerated, RevisionName_s, Log_s
| order by TimeGenerated desc

For system-level events (container restarts, replica provisioning, scaling events), use the ContainerAppSystemLogs_CL table instead. If you're seeing repeated replica restarts, this query will tell you the restart reason:

ContainerAppSystemLogs_CL
| where TimeGenerated > ago(2h)
| where ContainerAppName_s == "YOUR_APP_NAME"
| where Reason_s in ("OOMKilled", "CrashLoopBackOff", "Error")
| project TimeGenerated, Reason_s, Log_s
| order by TimeGenerated desc

OOMKilled means your container hit its memory limit. Increase your memory allocation in the container's resource settings. CrashLoopBackOff means your container is crashing repeatedly on startup, almost always a code or configuration error that shows up in the console logs.

Quota and Resource Limit Errors

Azure Container Apps environments have per-region quotas on vCPU and memory. If you're running multiple apps in the same environment and one of them fails to provision, you may have hit the environment's resource ceiling. Check your current usage:

az containerapp env show \
  --name YOUR_ENVIRONMENT_NAME \
  --resource-group YOUR_RESOURCE_GROUP \
  --query "properties.workloadProfiles"

If you're on the Consumption plan and hitting limits, you can request quota increases through the Azure portal under SubscriptionsUsage + quotas. Microsoft documents that these quotas can be overridden on a per-account basis, so this is a support ticket, not a hard technical limit.

Network-Level Issues with Virtual Networks

If you're running Azure Container Apps inside a custom virtual network (which you can provide when creating the environment), you may hit connectivity issues between your container app and other Azure resources. The most common problem is that the subnet delegated to Container Apps doesn't have the right NSG rules to allow outbound traffic to your downstream services.

Check that your subnet has a /23 or larger CIDR block, Container Apps requires this for environment-internal IP allocation. Smaller subnets will fail to provision new replicas during scaling events, which looks like a random intermittent outage.

For internal-only services (apps that should never be publicly reachable), use internal ingress with the built-in DNS-based service discovery. Internal container apps get a DNS name in the format APPNAME.ENVIRONMENT_DEFAULT_DOMAIN that resolves only within the environment. No public IP, no exposure, and it works without any additional networking configuration.

When to Call Microsoft Support

If you've worked through all of the above and your container app still won't provision, and your Log Analytics logs show errors from the system (not your application code), it's time to escalate. Specifically, escalate when you see error codes like ContainerProvisioningFailed with no corresponding application error, or when quota increase requests don't resolve scaling failures. Open a support case at Microsoft Support with your container app resource ID, the revision name, and the exact timestamps of the failures, this dramatically speeds up the investigation on their end.

Prevention & Best Practices

Getting Azure Container Apps working is one thing. Keeping it working, across multiple developers, multiple environments, and production traffic, takes some intentional setup. Here's what separates teams that have smooth container deployments from teams that are constantly fighting fires.

Use explicit image tags, never :latest. I mentioned this earlier, but it bears repeating as a formal practice. Every CI/CD build should tag your image with the Git commit SHA or a semantic version number. When you deploy myapp:abc1234, you know exactly what code is running. When you deploy myapp:latest, you know nothing. And when something breaks at 2am, "I don't know which version is in production" is a terrible starting position.

Separate secrets from configuration. Never bake connection strings, API keys, or passwords into your container image or pass them as plain environment variables. Azure Container Apps has a built-in secret store. Use it. If you're using Azure Key Vault for organization-wide secret management, you can reference Key Vault secrets directly in Container Apps using managed identity, no credentials in your deployment pipeline at all.

Test your container locally before deploying. This sounds obvious, but the gap between "works on my machine" and "works in Container Apps" is almost always caused by environment-specific assumptions, a local file path, a localhost URL, a missing env variable. Run your container image locally with the same environment variables it'll have in Azure:

docker run -p 3000:3000 \
  -e DB_CONNECTION_STRING="your-connection-string" \
  -e API_KEY="your-api-key" \
  your-registry/your-image:tag

If it works locally with those exact env vars, it'll work in Container Apps (assuming the ingress and registry are configured correctly).

Monitor proactively with Azure Log Analytics alerts. Don't wait for users to tell you something is broken. Set up alert rules in Azure Monitor that fire when your container app's replica count drops to zero unexpectedly, or when your error rate in Log Analytics spikes above a threshold. Five minutes of setup here saves hours of incident response later.

Quick Wins
  • Pin your container image tags to commit SHAs in your CI/CD pipeline, never deploy :latest to production.
  • Enable multiple-revision mode on all production container apps so you can roll back in 30 seconds without redeploying.
  • Always set CPU and memory limits explicitly, unset limits lead to quota exhaustion that affects all apps in your environment.
  • Create one Container Apps environment per stage (dev, staging, prod), sharing an environment between stages means a bad deployment in staging can exhaust resources for production.

Frequently Asked Questions

How can I make sure what works on my machine also works in Azure Container Apps?

The short answer is: build your image once, run it everywhere. Package your application and all its dependencies into the Docker image itself, don't rely on anything being installed on the host. Then run that exact image locally with docker run, passing environment variables that mirror your Azure Container Apps configuration. If it works locally with those variables, it'll behave the same in the cloud. The platform provides a consistent execution environment precisely because containers isolate your app from the underlying infrastructure differences. The most common breakage point is environment variables that exist in your local shell but weren't defined in the Container Apps secret or environment variable settings, always do a side-by-side comparison of your local env and your Azure env config.

How do I manage settings between dev, staging, and production in Azure Container Apps?

The cleanest approach is to use one Container Apps environment per stage, with environment-specific secrets and environment variables configured in each. Export your container app configuration as YAML (az containerapp show --output yaml) and store it in source control, then use environment-specific variable files or GitHub Actions secrets to inject the right values at deploy time. Never hardcode environment-specific values into your container image itself; that defeats the whole purpose of containerization. Keep your image identical across all environments and vary only the runtime configuration through environment variables and secrets.

How do I reliably deploy my Azure Container Apps application without downtime?

Switch to multiple-revision mode and use traffic splitting for all production deployments. Deploy your new version as a new revision, send it 5–10% of traffic, watch the error rates in Log Analytics for 10–15 minutes, then gradually shift more traffic over. If anything looks wrong, move traffic back to the old revision, no users experience downtime and no emergency rollback procedure is needed. This is the Blue/Green deployment pattern that Azure Container Apps supports natively. Pair this with explicit image tags and your deployment history is fully traceable through the revision list.

Why is my Azure Container Apps app not scaling up even though there's traffic?

Check three things in order: first, verify that your scaling rule is actually defined (navigate to Scale and replicas in the portal, or run az containerapp show --query "properties.template.scale"). Second, check that maxReplicas is greater than your current replica count, if max is set to 1 and you're already at 1, it won't scale. Third, if you're using a KEDA-based scaler (Service Bus, Event Hub, custom), verify the scaler's connection credentials are correct and the scaler can actually read the metric it's supposed to respond to. A KEDA scaler that can't authenticate to its data source will report 0 messages/events and keep your replica count at minimum.

My container app is running but I'm getting a 502 error. What does that mean?

A 502 Bad Gateway from Azure Container Apps almost always means ingress is reaching your container but the container isn't responding on the expected port. Double-check that the target port in your ingress settings exactly matches the port your application listens on inside the container. Then check your container logs (az containerapp logs show --type console) to see if the app is crashing shortly after startup, sometimes an app starts, fails to bind to a port due to a config error, and the platform keeps routing traffic to a dead process. If your app needs time to initialize before it can serve traffic, consider adding a startup probe or increasing the startupProbe delay in your revision configuration.

What is the difference between Azure Container Apps and Azure Kubernetes Service (AKS)?

Azure Container Apps is designed for teams who want to run containerized applications without managing Kubernetes directly. You don't configure nodes, namespaces, ingress controllers, or cluster upgrades, the platform does all of that. AKS gives you a fully managed Kubernetes cluster where you control nearly everything: node pools, networking policies, custom operators, the works. Container Apps is the right choice for microservices, API backends, background jobs, and event-driven workloads where you want to focus on your application code. AKS makes sense when you have complex orchestration needs, specific Kubernetes extensions, or compliance requirements that need direct cluster access. Most new projects benefit from starting with Container Apps and only moving to AKS if specific limitations force the upgrade.

Related Microsoft Fix Guides

H
Sai Kiran Pandrala
Our team includes certified Microsoft engineers, Azure architects, and system administrators with 10+ years of enterprise IT experience. Every guide is written from hands-on troubleshooting, not guesswork. We test every fix before publishing.