Why can my Docker container not connect to a service on localhost?
Inside a container, localhost means the container itself, not the machine running it. Each container has its own network namespace and its own loopback interface, so a connection to localhost from inside reaches only processes in that same container. That is why a database running happily on your machine is unreachable and the error is a flat connection refusal.
What to use instead depends on where the other service actually is.
- Another container in the same compose project. Use the service name as the hostname. Compose puts them on a shared network with DNS entries for each service, so the name resolves to that container address. Use the port the service listens on inside the container, not the port published to your machine, because you are not going via the host at all.
- A service on the host machine. Docker provides a special hostname for this on desktop platforms which resolves to the host from inside a container. On Linux it is available in recent versions but may need declaring explicitly as an extra host entry.
- A container on a different network. Containers can only reach each other by name if they share a user-defined network, so attaching both to the same network is the fix.
A closely related mistake sits on the listening side. A service bound to the loopback interface inside its container accepts connections only from that container, no matter how ports are published. Binding to all interfaces is required for anything expected to receive outside traffic.
When debugging, opening a shell inside the container and attempting the connection from there is far more informative than testing from the host, because it exercises the same namespace and DNS resolution your application actually uses.