Docker "Port Is Already Allocated" + Nginx/Docker 502 Bad Gateway: Decision-Path Triage (2026)
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: 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
- Core pages return
200over HTTPS. - Target backend containers are
Upwith stable restart counts. - Nginx active state is
activeand no fresh upstream-connect errors appear.
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.