How to Fix Docker 502 Bad Gateway on Google Cloud Run
The Root Cause
This error on Google Cloud Run typically indicates that the Cloud Run proxy cannot connect to your containerized application. The primary reason is often the application inside the Docker container not listening on the port specified by the PORT environment variable (which Cloud Run sets to 8080 by default).
Quick Fix (CLI)
To resolve this immediately, ensure your Cloud Run service is configured to expect traffic on port 8080 and trigger a redeployment. This assumes your application is built to listen on the PORT environment variable or 8080 by default.
# Replace YOUR_SERVICE_NAME, YOUR_REGION, YOUR_PROJECT_ID, and YOUR_IMAGE_NAME
# with your specific values.
# Trigger a redeployment, explicitly ensuring Cloud Run expects traffic on port 8080.
# This also passes PORT=8080 as an environment variable to your container.
gcloud run deploy YOUR_SERVICE_NAME \
--image gcr.io/YOUR_PROJECT_ID/YOUR_IMAGE_NAME:latest \
--region YOUR_REGION \
--port 8080 \
--no-allow-unauthenticated # Use --allow-unauthenticated if your service is public
Configuration Check
The critical configuration to verify is within your application’s code or its Dockerfile. Your application must explicitly listen on the port provided by the PORT environment variable, or default to 8080.
File to edit: Your application’s main server file (e.g., app.js, main.py, server.go) and/or your Dockerfile.
Lines to change:
1. Application Code (Example: Node.js):
Ensure your application’s server initialization uses process.env.PORT (or equivalent for your language) and falls back to 8080.
// Before (if hardcoded to a different port like 3000):
// const PORT = 3000;
// app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
// After (correct):
const PORT = process.env.PORT || 8080; // Listen on PORT env var, or 8080 as fallback
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
2. Dockerfile (Example: Python with Gunicorn):
Ensure your EXPOSE instruction is 8080 and your CMD or ENTRYPOINT passes the $PORT environment variable to your application.
# Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8080 # This declares the port your container listens on.
# CMD exec gunicorn --bind 0.0.0.0:5000 app:app # Before (if hardcoded)
# After (correct): The application listens on the port provided by the $PORT env var.
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
Verification
After redeploying your service, verify the fix by attempting to access the service URL and checking the Cloud Run logs for successful application startup messages.
# 1. Retrieve the service URL and attempt to access it
SERVICE_URL=$(gcloud run services describe YOUR_SERVICE_NAME --region YOUR_REGION --format='value(status.url)')
echo "Attempting to access: $SERVICE_URL"
curl -I "$SERVICE_URL"
# Expected: HTTP/2 200 (or another successful status code), not 502 Bad Gateway.
# 2. Inspect Cloud Run container logs for successful startup messages
# Look for messages indicating your application is listening on the expected port (8080).
gcloud run logs read YOUR_SERVICE_NAME \
--region YOUR_REGION \
--limit=20 \
--format='value(textPayload)' | grep -i 'listening on port 8080'
# Expected: Output showing your application's log line confirming it's listening on port 8080.