How to Fix Nginx Fatal Error on Google Cloud Run
The Root Cause
“Nginx Fatal Error” on Google Cloud Run commonly stems from Nginx attempting to bind to a restricted port (e.g., 80 or 443) instead of the Cloud Run-assigned $PORT (typically 8080), or trying to write PID/log files to a read-only filesystem location without proper configuration. Additionally, Nginx running in daemon mode (default) within a container entrypoint can lead to the container exiting prematurely or failing health checks.
Quick Fix (CLI)
After applying the configuration changes detailed below in your Dockerfile and nginx.conf, rebuild your container image and deploy it to Cloud Run.
# 1. Set your Google Cloud project ID
PROJECT_ID=$(gcloud config get-value project)
# 2. Build the Docker image (assuming your Dockerfile is in the current directory)
docker build -t gcr.io/${PROJECT_ID}/nginx-app:latest .
# 3. Push the image to Google Container Registry (GCR) or Artifact Registry
docker push gcr.io/${PROJECT_ID}/nginx-app:latest
# 4. Deploy the updated service to Cloud Run
# Replace 'your-service-name', 'your-region', and other flags as necessary
gcloud run deploy your-service-name \
--image gcr.io/${PROJECT_ID}/nginx-app:latest \
--platform managed \
--region us-central1 \
--allow-unauthenticated # Or specify appropriate authentication settings
Configuration Check
The primary files to modify are your nginx.conf and Dockerfile.
1. nginx.conf
Edit your nginx.conf file to ensure Nginx listens on the correct port and logs to standard output/error, which Cloud Run captures.
# Add or modify these lines within your nginx.conf
# Ensure Nginx runs in foreground, critical for container environments.
daemon off;
# Use a non-privileged user if possible, and ensure it has necessary permissions.
# user nginx; # Uncomment if your Dockerfile sets up a dedicated Nginx user.
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Log access and errors to stdout/stderr for Cloud Run's logging system.
access_log /dev/stdout;
error_log /dev/stderr warn;
server {
# Cloud Run sets the $PORT environment variable. Nginx must listen on it.
# This line assumes $PORT is injected (see Dockerfile below).
# If not using envsubst, you can hardcode listen 8080; if $PORT is always 8080.
listen 0.0.0.0:${PORT};
# Other server configurations...
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}
2. Dockerfile
Modify your Dockerfile to copy the updated nginx.conf and set the correct command to run Nginx, typically using envsubst to inject the $PORT environment variable.
# Use a lean Nginx base image
FROM nginx:alpine
# Copy your custom Nginx configuration template
# Use .template suffix to distinguish from the runtime config
COPY nginx.conf /etc/nginx/nginx.conf.template
# Cloud Run injects the $PORT environment variable (default: 8080).
# We use envsubst to replace ${PORT} in our template config with the actual value.
# The result is written to /etc/nginx/conf.d/default.conf, which Nginx uses.
# The `nginx -g 'daemon off;'` command ensures Nginx runs in the foreground.
CMD sh -c "envsubst '\$PORT' < /etc/nginx/nginx.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
# Optional: Set an exposed port, mainly for documentation or local testing.
EXPOSE 8080
Verification
After redeploying your service, use the following commands to verify the fix:
# 1. Check the service status and latest revision details.
# Look for 'Ready: True' and 'traffic: 100%' for the latest revision.
gcloud run services describe your-service-name \
--platform managed \
--region us-central1
# 2. View container logs to ensure Nginx started without errors.
# Look for Nginx startup messages and absence of "Fatal" or "emerg" logs.
gcloud run services logs read your-service-name \
--platform managed \
--region us-central1 \
--limit 20 # Adjust limit as needed
# 3. Access the service URL in your browser or via curl to confirm connectivity.
# Replace with the actual URL provided by `gcloud run services describe`.
curl https://your-service-url.run.app