Docker "Port Is Already Allocated" + Nginx/Docker 502 Bad Gateway: Decision-Path Triage (2026)

Published March 1, 2026 · 10 min read

Fix It With a Tool

Validate compose and upstream targets first

Use one pass for port mappings and upstream config so you stop switching between Docker and Nginx symptoms blindly.

Use this guide when errors alternate: deploy logs show port is already allocated or bind: address already in use, while users hit 502 Bad Gateway. If your incident is only one side, start with Docker port-allocation fix or Nginx reverse proxy troubleshooting. If timeout errors dominate (upstream timed out), use the nginx upstream timed out docker matrix.

Mixed incidents happen because one failure class cascades into another. A blocked Docker publish keeps a backend unavailable, and Nginx then reports upstream failure. This guide keeps triage deterministic with one cause taxonomy and command path.

Table of contents

  1. Cause taxonomy and symptom mapping
  2. Decision path with fix commands
  3. Recovery verification checklist
  4. FAQ

1. Cause taxonomy: map the first signal before changing config

Signal pair Likely root cause First command set
Docker publish fails + Nginx 502 Host port collision (process/container already owns host socket) ss -ltnp, docker ps -a
Nginx 502 after deploy, no bind error now Backend container down or crash-looping docker compose ps, docker logs
Nginx 502 with healthy container Wrong upstream target/address mismatch nginx -T, curl backend directly
Intermittent 502 during reboot/startup Network bridge/startup ordering race systemctl status, journalctl

2. Decision path: choose one branch, fix once, verify

Branch A: Host port collision

Symptoms: Docker shows port is already allocated, driver failed programming external connectivity, or bind address in use.

ss -ltnp | rg ':80|:443|:8080|:3000' || true
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
docker compose config

Fix commands:

docker compose down --remove-orphans
docker container prune -f
# remap conflicting host port if needed (example)
# from 8080:8080 -> 8081:8080
docker compose up -d --force-recreate

Deep dive: port-allocation decision flow.

Branch B: Backend container down after prior bind failure

Symptoms: Nginx returns 502, Docker publish error no longer shown, but app container exited or restarting.

docker compose ps
docker logs --tail=120 <backend_container>
docker inspect <backend_container> --format '{{.State.Status}} {{.State.RestartCount}}'

Fix commands: resolve startup defect, then redeploy once.

docker compose up -d --force-recreate
docker compose ps

If restarts continue, use restart-loop decision tree.

Branch C: Upstream target mismatch (Nginx points to wrong host/port)

Symptoms: backend is running, but Nginx still logs connect() failed or no live upstreams.

sudo nginx -T | rg -n 'upstream|proxy_pass'
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:<backend_port>/health || true

Fix commands: align proxy_pass target with real backend listener, then reload Nginx.

sudo nginx -t
sudo systemctl reload nginx

Reference: Nginx 502 troubleshooting checklist.

Branch D: Startup ordering or bridge-path race

Symptoms: failures cluster around reboot; one service starts before upstream/bridge path is ready.

sudo systemctl status nginx --no-pager
sudo journalctl -u nginx -n 80 --no-pager
ip -4 addr show

Fix pattern: enable service restart on failure and verify the backend path is reachable after boot.

sudo systemctl show nginx -p Restart -p RestartUSec
curl -sS -o /dev/null -w '%{http_code}\n' https://devtoolbox.dedyn.io/

3. Recovery verification checklist (must pass all)

# Endpoint checks
curl -sS -o /dev/null -w '%{http_code}\n' https://devtoolbox.dedyn.io/
curl -sS -o /dev/null -w '%{http_code}\n' https://devtoolbox.dedyn.io/blog/
curl -sS -o /dev/null -w '%{http_code}\n' https://devtoolbox.dedyn.io/tools/

# Runtime checks
docker compose ps
sudo systemctl is-active nginx

4. FAQ

Why do I get both "port is already allocated" and "nginx 502 bad gateway" in one outage?

A failed Docker port publish can keep the backend unavailable while Nginx still accepts requests. That produces 502 for users and port-bind errors in deploy logs.

How do I fix "bind: address already in use" in Docker Compose?

Identify the current socket owner with ss -ltnp (or lsof -i), then stop/remap the conflicting process or container and redeploy with a unique host port mapping.

What does "connect() failed (111: Connection refused) while connecting to upstream" mean?

Nginx reached the upstream endpoint but nothing accepted the connection. Check container health, listener port/address, and proxy_pass target alignment.