Docker networking troubleshooting starts by identifying where the failing request originates. The browser, host, reverse proxy, application container, and remote service each have a different network view.
Use read-only inspection first. Broad cleanup commands can destroy evidence, disconnect healthy services, or remove data without fixing the underlying problem.
Write down the expected path
Browser -> HTTPS entry point -> application host port
-> application container -> service DNS name -> dependency
An application container should normally reach another Compose service using its service name and container port. The host can reach a published host port. These are different addresses, even when they point to the same service.
localhost inside a container refers to that container. A database URL pointing to localhost therefore fails unless the database shares that network namespace.
Inspect the actual deployment
Run from the directory containing the intended Compose project:
docker compose ps
docker compose config --quiet
docker compose logs --tail=100 api
docker network ls
docker inspect APP_CONTAINER --format '{{json .NetworkSettings.Networks}}'
docker port APP_CONTAINER
ss -ltn
Replace APP_CONTAINER and api with your actual names. Do not publish full container inspection or resolved configuration output: environment variables and labels may contain private information.
Check that both services belong to a shared network. A running container with no expected network attachment can be alive but unreachable. Investigate daemon logs and network restoration errors after a host reboot before assuming the application is broken.
Test each layer separately
| Observation | Likely next check |
|---|---|
| Name does not resolve | Shared network, service name, container DNS |
| Connection refused | Listener, port, bind address, service startup |
| Connection times out | Routing, firewall, network policy, hung server |
| HTTP 401 or 403 | Authentication and authorization |
| Host works, container fails | Container routing, DNS, proxy, destination binding |
| Short calls work, streams fail | Proxy buffering, timeouts, cancellation |
Use the application's installed runtime for a small diagnostic request if the image has no curl. Avoid installing debugging tools into a production container just to make one request; a temporary diagnostic container on the same network can be safer when approved.
Understand published interfaces
A binding such as 127.0.0.1:8080:3000 exposes container port 3000 only through host loopback. A binding on all interfaces has a different exposure. Inspect actual listeners and firewall policy rather than assuming a port is private.
If a container binds a host VPN address, startup can fail when that address is not yet available. Fix the intended service ordering or binding policy; do not automatically broaden it to all interfaces.
Repair narrowly
After correcting configuration, recreate only the affected service when possible. Preserve named volumes and bind-mounted data. Network names and Compose project names matter: starting from a different directory can create a different project rather than repair the existing one.
Do not use docker system prune --volumes, global daemon restarts, or down -v as first-line network repair. After any fix, test application behavior and a controlled restart so the problem does not return at the next reboot.