How to Fix Nginx 502 Bad Gateway on Google Cloud Run
The Root Cause
On Google Cloud Run, an Nginx 502 Bad Gateway error typically signifies that the Nginx server, running as the primary process within your container, failed to connect to its upstream application server. This most often occurs because the application process, which Nginx is configured to proxy requests to (e.g., localhost:8081), is either not running, has crashed, or is not listening on the expected port inside the container instance.
Quick Fix (CLI) The quickest CLI approach to resolve a transient or resource-related 502 is to force a redeployment with potentially increased resources or startup timeout, which can help if the issue is due to slow application initialization or resource starvation. If the problem persists, rolling back to a previously stable revision is the most immediate fix for configuration errors.
# Option 1: Redeploy with increased startup resources and timeout
# Use if application is slow to initialize or facing temporary resource constraints.
gcloud run services update SERVICE_NAME \
--region=REGION \
--cpu=1 \
--memory=1Gi \
--startup-timeout=300s # Increase startup timeout to 5 minutes (default is 60s)
# Option 2: Roll back to a previous stable revision
# Use if a recent deployment introduced a configuration error.
# First, list available revisions to identify a working one:
gcloud run revisions list --service=SERVICE_NAME --region=REGION
# Then, update the service to point to the stable revision ID:
# Replace PREVIOUS_WORKING_REVISION with the actual revision ID (e.g., service-00005-xyz)
gcloud run services update SERVICE_NAME \
--region=REGION \
--to-revision=PREVIOUS_WORKING_REVISION
Configuration Check
The primary challenge on Cloud Run is that only one main process can be executed by the container’s CMD or ENTRYPOINT. If Nginx is serving as a reverse proxy to another application within the same container, you need a custom entrypoint script to launch both processes. Ensure the PORT environment variable (default 8080) is respected by Nginx, and your application listens on a different internal port.
File: Dockerfile
Ensure your Dockerfile correctly sets up the Nginx process to listen on the Cloud Run PORT and a mechanism to start your application server. A common pattern uses an entrypoint.sh script.
# 1. Set the port Cloud Run expects Nginx to listen on
ENV PORT 8080
EXPOSE $PORT
# 2. Copy your Nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf
# 3. Copy a custom entrypoint script to launch both Nginx and your application
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
# 4. Use the entrypoint script
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
# --- Example of what 'entrypoint.sh' should contain ---
# #!/bin/bash
#
# # Start your application in the background on an internal port (e.g., 8081)
# # Replace /path/to/your/application-binary with the actual command to start your app.
# # Ensure your application is configured to listen on a specific port (e.g., 8081).
# /path/to/your/application-binary --port=8081 &
#
# # Start Nginx in the foreground, listening on $PORT (8080) and proxying to 8081
# exec nginx -g "daemon off;"
File: /etc/nginx/nginx.conf
Nginx must be configured to listen on the PORT environment variable (default 8080) that Cloud Run directs traffic to. It must then proxy requests to the internal port where your application is actually listening (e.g., localhost:8081). Incorrect proxy_pass directives or insufficient proxy timeouts are common causes for 502s.
# --- Example nginx.conf snippet ---
server {
# Nginx must listen on the port Cloud Run assigns (default 8080)
listen 8080 default_server;
listen [::]:8080 default_server;
location / {
# IMPORTANT: Ensure this points to the *correct* internal port your application is listening on.
# DO NOT set this to 8080 if Nginx is also listening on 8080.
proxy_pass http://localhost:8081; # <-- Application's internal port (e.g., 8081)
# Add or adjust these proxy headers and timeouts
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Increase timeouts if the application takes longer to respond
proxy_connect_timeout 60s; # How long Nginx waits to connect to upstream
proxy_send_timeout 60s; # How long Nginx waits for upstream to send data
proxy_read_timeout 60s; # How long Nginx waits for upstream to read data
}
# For more detailed Nginx error reporting, log to stderr for Cloud Run to capture
error_log /dev/stderr debug;
}
Verification After deploying the fix, verify the service is functioning correctly.
# 1. Get the URL of your deployed Cloud Run service
SERVICE_URL=$(gcloud run services describe SERVICE_NAME --region=REGION --format="value(status.url)")
# 2. Make a request to the service to check its HTTP status
curl -v "${SERVICE_URL}"
# Expected output: Look for "HTTP/2 200 OK" or similar success status code.
# A 5xx status still indicates an issue, likely within the application itself.
# 3. Check Cloud Run logs for any Nginx or application errors
# Look for messages indicating successful startup of both Nginx and your application.
# Search for Nginx errors, application startup failures, or unhandled exceptions.
gcloud run services logs read SERVICE_NAME --region=REGION --limit=50 --format=json | jq '.[] | {timestamp: .timestamp, severity: .severity, textPayload: .textPayload}'
# To filter specifically for Nginx-related log entries:
gcloud run services logs read SERVICE_NAME --region=REGION --limit=50 | grep "nginx"