How to Fix Docker 502 Bad Gateway on AWS EC2


The Root Cause On AWS EC2, a Docker 502 Bad Gateway primarily indicates that the upstream Docker container is either not running, has crashed, or is not listening on the port that the reverse proxy (e.g., Nginx, ALB/NLB) expects. Additionally, AWS Security Groups might be preventing the proxy or external traffic from reaching the EC2 instance’s exposed Docker port, leading to a connection refused error on the proxy side.

Quick Fix (CLI)

# 1. List all Docker containers to identify the problematic one and its status
sudo docker ps -a

# 2. Inspect logs of the stopped or unhealthy container for crash details or errors
# Replace <container_id_or_name> with the actual ID or name from `docker ps -a`
sudo docker logs <container_id_or_name>

# 3. If the container is stopped or recently crashed, attempt to restart it
sudo docker restart <container_id_or_name>

# 4. If restarting doesn't resolve the issue, verify resource usage (e.g., OOM kills)
sudo dmesg | grep -i "killed process"

Configuration Check

  • File to edit: Typically /etc/nginx/sites-available/default (or a custom Nginx service configuration file) on your EC2 instance, and your docker-compose.yml or the docker run command used to start the container.

  • Lines to change:

    1. Nginx Reverse Proxy Configuration: Verify the proxy_pass directive targets the correct host port exposed by your Docker container.

      # Example: /etc/nginx/sites-available/default
      server {
          listen 80;
          server_name your_domain.com your_ec2_ip;
      
          location / {
              # Ensure '8080' (or your designated port) matches the *host port*
              # where Docker exposes your container on the EC2 instance.
              proxy_pass http://localhost:8080;
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              # ... other proxy directives ...
          }
      }
    2. Docker Port Mapping: Ensure the Docker container is exposing its internal application port to the correct host port that Nginx (or your ALB/NLB) is configured to connect to.

      • If using docker run: Verify the -p host_port:container_port flag. sudo docker run -d -p 8080:3000 --name my-app my-image:latest (Here, 8080 is the host port Nginx should connect to, and 3000 is the port your application inside the container listens on.)
      • If using docker-compose.yml: Verify the ports section for your service.
        services:
          web:
            image: your_app_image
            ports:
              - "8080:3000" # host_port:container_port
        Ensure the host_port (e.g., 8080 in these examples) in Docker’s mapping exactly matches the port specified in Nginx’s proxy_pass directive.
    3. AWS Security Groups: In the AWS EC2 console, navigate to Security Groups. Select the Security Group associated with your EC2 instance. In the “Inbound rules” tab, confirm that the host_port (e.g., 8080) is open to traffic from either 0.0.0.0/0 (for public access) or from your Load Balancer’s security group.

Verification

# 1. If Nginx configuration was changed, test its syntax and reload it
sudo nginx -t && sudo systemctl reload nginx

# 2. Verify the Docker container is now running and healthy
sudo docker ps

# 3. Attempt to access the application directly from the EC2 instance using curl
# Replace <docker_exposed_host_port> (e.g., 8080) with the actual host port
curl http://localhost:<docker_exposed_host_port>/

# Expected: Your application's HTTP response (e.g., HTML, JSON). If this works,
# but external access still fails, review AWS Security Groups and Load Balancer health checks.