Skip to content

Ingress Not Reachable

1. Summary

Symptom

HTTP requests to your Container App's FQDN fail with timeout, 502 Bad Gateway, or 504 Gateway Timeout errors. DNS may resolve correctly, but the application is not serving traffic. Errors can be intermittent or sustained.

Why this scenario is confusing

Ingress failures have many possible causes spanning DNS, networking, revision health, and probe configuration. A working revision doesn't guarantee reachability—ingress mode, target port, and backend health all contribute to the final outcome.

Troubleshooting decision flow

graph TD
    A[Symptom: Endpoint unreachable] --> B{DNS resolves to correct IP?}
    B -->|No| H1[H1: DNS/Environment misconfiguration]
    B -->|Yes| C{Ingress enabled and mode correct?}
    C -->|No| H2[H2: Ingress mode mismatch]
    C -->|Yes| D{Healthy replicas running?}
    D -->|No| H3[H3: No healthy backend]
    D -->|Yes| E{Target port matches app?}
    E -->|No| H4[H4: Target port mismatch]
    E -->|Yes| F{Network path clear?}
    F -->|No| H5[H5: Firewall/NSG blocking]
    F -->|Yes| G[Investigate app-level issues]

2. Common Misreadings

  • "DNS is broken" — Many reachability issues are actually unhealthy replicas or wrong target port, not DNS.
  • "Ingress external means always public" — NSGs, firewalls, and private environment routing still apply.
  • "The revision is running, so ingress should work" — Revision running ≠ healthy replicas passing probes.
  • "502 means platform issue" — Often indicates backend unhealthy or probe failures, not platform bugs.
  • "It works from my machine" — Different network paths (VNet, internet, private endpoint) have different reachability.

3. Competing Hypotheses

Hypothesis Typical Evidence For Typical Evidence Against
H1: DNS/Environment misconfiguration NXDOMAIN, wrong IP resolved, environment domain mismatch DNS resolves to correct environment IP
H2: Ingress mode mismatch external=false but tested from internet, or vice versa Internal caller succeeds from same VNet
H3: No healthy backend replicas HealthState=Unhealthy, 0 running replicas, probe failures Multiple healthy replicas serving requests
H4: Target port mismatch 502 with app logs showing no incoming requests, app listening on different port App and target port aligned, health probes pass
H5: Firewall/NSG blocking Timeout from specific networks, works from others Same behavior from all network locations

4. What to Check First

Metrics

  • Request count with 5xx spikes and low success ratio
  • Replica count over time (should be > 0)
  • Ingress latency percentiles (P50, P95, P99)

Logs

let AppName = "ca-myapp";
ContainerAppSystemLogs_CL
| where ContainerAppName_s == AppName
| where TimeGenerated > ago(1h)
| where Log_s has_any ("ingress", "502", "503", "504", "connection refused", "timeout", "upstream", "gateway")
| project TimeGenerated, RevisionName_s, Reason_s, Log_s
| order by TimeGenerated desc

Platform Signals

# Check ingress configuration
az containerapp show --name "$APP_NAME" --resource-group "$RG" \
  --query "properties.configuration.ingress" --output json

# Check revision health and traffic weights
az containerapp revision list --name "$APP_NAME" --resource-group "$RG" \
  --query "[].{name:name,active:properties.active,replicas:properties.replicas,health:properties.healthState,traffic:properties.trafficWeight}" \
  --output table

# Check replica status
az containerapp replica list --name "$APP_NAME" --resource-group "$RG" --output table
Command Purpose
az containerapp show --name "$APP_NAME" --resource-group "$RG" --query "properties.configuration.ingress" --output json Reads the Container App resource and extracts the effective ingress configuration in structured form for operator review, which is the specific surface this troubleshooting step needs to confirm.
az containerapp revision list --name "$APP_NAME" --resource-group "$RG" --query "[].{name:name,active:properties.active,replicas:properties.replicas,health:properties.healthState,traffic:properties.trafficWeight}" --output table Lists revisions and filters them to the health, traffic, or timing fields needed for this hypothesis, so you can see whether rollout state matches the failure pattern.
az containerapp replica list --name "$APP_NAME" --resource-group "$RG" --output table Lists live replicas so you can confirm how many instances exist and whether the platform is creating, restarting, or recycling them.

5. Evidence to Collect

Required Evidence

Evidence Command/Query Purpose
Ingress config az containerapp show ... --query ingress Verify mode, port, transport
Revision list az containerapp revision list Check health state and traffic weights
Replica list az containerapp replica list Confirm running replicas exist
System logs KQL on ContainerAppSystemLogs_CL Find ingress/probe errors
DNS resolution nslookup <fqdn> or dig <fqdn> Verify DNS resolves correctly

Useful Context

  • Environment networking mode (VNet-integrated or consumption-only)
  • Custom domain configuration (if applicable)
  • Recent deployment or configuration changes
  • Network path of the caller (internet, VNet, private endpoint)

6. Validation and Disproof by Hypothesis

H1: DNS/Environment misconfiguration

Signals that support:

  • nslookup returns NXDOMAIN or unexpected IP
  • Environment default domain doesn't match expected pattern
  • Custom domain verification incomplete

Signals that weaken:

  • DNS resolves to correct environment IP
  • Same FQDN works from other clients

What to verify:

# Check DNS resolution
nslookup $(az containerapp show --name "$APP_NAME" --resource-group "$RG" \
  --query "properties.configuration.ingress.fqdn" --output tsv)

# Check environment domain
az containerapp env show --name "$ACA_ENV_NAME" --resource-group "$RG" \
  --query "properties.defaultDomain" --output tsv
Command Why it is used
az containerapp show --name ... Reads the Container App configuration so the documented setting can be verified.

H2: Ingress mode mismatch

Signals that support:

  • external: false but testing from public internet
  • Works from VNet but not from internet (or vice versa)
  • 404 or timeout only from specific network locations

Signals that weaken:

  • Ingress mode matches test scenario
  • Same error from both internal and external callers

What to verify:

# Check ingress external setting
az containerapp show --name "$APP_NAME" --resource-group "$RG" \
  --query "properties.configuration.ingress.external" --output tsv

# Expected: true for public access, false for VNet-only
Command Why it is used
az containerapp show --name ... Reads the Container App configuration so the documented setting can be verified.

H3: No healthy backend replicas

Signals that support:

  • HealthState: Unhealthy or Degraded in revision list
  • Replica count is 0 or replicas show Terminated status
  • System logs show ProbeFailed, ContainerTerminated, CrashLoopBackOff
  • 502/503 errors with backend probe failure messages

Signals that weaken:

  • Multiple Healthy replicas in Running state
  • Successful responses intermixed with failures

What to verify:

# Check revision health
az containerapp revision list --name "$APP_NAME" --resource-group "$RG" \
  --query "[?properties.active].{name:name,health:properties.healthState,replicas:properties.replicas}" \
  --output table

# Check replica status
az containerapp replica list --name "$APP_NAME" --resource-group "$RG" --output table
Command Why it is used
az containerapp revision list ... Lists revisions so rollout state, traffic, and health can be verified.

KQL for probe failures:

let AppName = "ca-myapp";
ContainerAppSystemLogs_CL
| where ContainerAppName_s == AppName
| where TimeGenerated > ago(1h)
| where Reason_s in ("ProbeFailed", "ContainerTerminated", "Unhealthy")
| summarize count() by Reason_s, RevisionName_s
| order by count_ desc

H4: Target port mismatch

Signals that support:

  • 502 errors but no incoming requests in app console logs
  • App configured to listen on port 3000 but targetPort: 8000
  • Probe failures with "connection refused"

Signals that weaken:

  • App console logs show incoming requests
  • Target port matches EXPOSE in Dockerfile and app bind

What to verify:

# Check target port
az containerapp show --name "$APP_NAME" --resource-group "$RG" \
  --query "properties.configuration.ingress.targetPort" --output tsv

# Check app's actual listening port (from container config or Dockerfile)
az containerapp show --name "$APP_NAME" --resource-group "$RG" \
  --query "properties.template.containers[0].env[?name=='PORT' || name=='CONTAINER_APP_PORT']" \
  --output table
Command Purpose
az containerapp show --name "$APP_NAME" --resource-group "$RG" --query "properties.configuration.ingress.targetPort" --output tsv Reads the Container App resource and extracts the ingress target port as plain text for reuse in later commands, which is the specific surface this troubleshooting step needs to confirm.
az containerapp show --name "$APP_NAME" --resource-group "$RG" --query "properties.template.containers[0].env[?name=='PORT' || name=='CONTAINER_APP_PORT']" --output table Reads the Container App resource and extracts the container environment-variable mapping, which is the specific surface this troubleshooting step needs to confirm.
Command Why it is used
az containerapp show --name ... Reads the Container App configuration so the documented setting can be verified.

H5: Firewall/NSG blocking

Signals that support:

  • Timeout from specific source networks only
  • Works from Azure Cloud Shell but not corporate network
  • VNet has NSG rules blocking inbound 443/80

Signals that weaken:

  • Same behavior from all network locations
  • NSG logs show traffic allowed

What to verify:

# For VNet-integrated environments, check NSG rules
az network nsg rule list --resource-group "$RG" --nsg-name "$NSG_NAME" --output table

# Test from different network locations
curl --verbose --connect-timeout 10 "https://${APP_FQDN}/health"
Command Purpose
az network nsg rule list --resource-group "$RG" --nsg-name "$NSG_NAME" --output table Lists the NSG rules on the ingress path so you can confirm whether a network policy block explains why only certain caller networks time out.
curl --verbose --connect-timeout 10 "https://${APP_FQDN}/health" Tests the app endpoint from the current client path and shows connection, TLS, and HTTP details, which helps separate network blocking from application failures.

7. Likely Root Cause Patterns

Pattern Frequency First Signal Typical Resolution
Probe failure cascade Very common System logs: ProbeFailed Fix probe config or app startup
Target port mismatch Common 502 + no app traffic Align targetPort with app
Ingress disabled Common 404 or connection refused Enable ingress
Revision not activated Occasional 0 traffic weight Set traffic weight > 0
VNet routing issues Occasional Timeout from VNet only Check UDR and private DNS

8. Immediate Mitigations

  1. If no healthy replicas: Roll back to previous healthy revision
    az containerapp ingress traffic set --name "$APP_NAME" --resource-group "$RG" \
      --revision-weight "<previous-healthy-revision>=100"
    
Command Why it is used
az containerapp ingress traffic ... Runs the Azure CLI operation required by the documented step.
  1. If target port mismatch: Update ingress target port
    az containerapp ingress update --name "$APP_NAME" --resource-group "$RG" \
      --target-port 8000
    
Command Why it is used
az containerapp ingress update ... Updates ingress settings on an existing Container App.
  1. If probe too aggressive: Relax probe settings temporarily
    az containerapp update --name "$APP_NAME" --resource-group "$RG" \
      --set-env-vars "PROBE_INITIAL_DELAY=30"
    
Command Why it is used
az containerapp update --name ... Updates the existing Container App configuration without recreating the app.
  1. If ingress disabled: Enable ingress
    az containerapp ingress enable --name "$APP_NAME" --resource-group "$RG" \
      --type external --target-port 8000 --transport http
    
Command Why it is used
az containerapp ingress enable ... Enables ingress for workloads that must receive inbound traffic.

9. Prevention

  • Include endpoint smoke tests in release pipeline
  • Alert on sustained 5xx increase and zero healthy replicas
  • Validate ingress config in IaC templates before deployment
  • Use health check endpoints that verify actual app readiness
  • Document expected ingress mode and FQDN in runbooks

See Also

Sources