Systems troubleshooting guide9 min read

Why localhost works on the host but not in Docker

Inside a container, localhost names the container itself—not your laptop and not another container. Trace the intended connection in both directions before changing bind addresses or publishing ports.

Reviewed by the Terminaster editorial team · Updated

What you will take away

  • Every container has its own network namespace and its own loopback interface.
  • A host service bound only to 127.0.0.1 is not automatically reachable from a container.
  • Publishing a port exposes a container listener to the host; it does not make host localhost appear inside the container.
  • Use service names for container-to-container traffic and platform-supported host routing for container-to-host traffic.

Identify which side is the client

“Localhost fails in Docker” can describe two opposite paths. A browser on the host may be trying to reach a server in a container, or an application in a container may be trying to reach a server on the host. The required configuration is different.

Within a normal container network namespace, 127.0.0.1 and ::1 lead back to that container. If an application in container A connects to localhost, it does not reach container B even when both belong to the same Compose project.

  • Host to container: check the container listener and published port.
  • Container to host: check the host service bind and the platform’s host address.
  • Container to container: use the other service’s network name and container port.
  • Host networking changes these assumptions and is platform-dependent; verify before relying on it.

Trace a host-to-container request

A published port maps a host address and port to a container port. The process inside the container must still listen on an address reachable through the container interface. A development server bound only to 127.0.0.1 inside the container commonly defeats the mapping.

Inspect both Docker’s mapping and the socket inside the container. Do not infer the internal listener from the presence of a PORTS entry alone.

Inspect a published web service

docker ps --format 'table {{.Names}}\t{{.Ports}}'
docker port web

docker exec web ss -ltn
# Then test the published host endpoint
curl -v --connect-timeout 5 --max-time 15 http://127.0.0.1:8080/

Trace a container-to-host request

Docker Desktop provides the special DNS name host.docker.internal for reaching host services from containers. With plain Linux Engine, add an explicit host-gateway mapping when you need that name: use `--add-host host.docker.internal:host-gateway` with docker run or the equivalent Compose extra_hosts entry.

The host service must listen on an address reachable from the container path. Changing a bind from loopback to a broader address affects exposure, so pair the change with appropriate access controls instead of treating 0.0.0.0 as a universal fix.

Test from inside a container

docker run --add-host host.docker.internal:host-gateway IMAGE

# Compose service equivalent:
extra_hosts:
  - "host.docker.internal:host-gateway"

# After starting the container:
docker exec app getent hosts host.docker.internal
docker exec app curl -v --connect-timeout 5 --max-time 15 \
  http://host.docker.internal:3000/

Use the service name between containers

Containers attached to the same user-defined Docker network can discover one another by container or Compose service name. Connect to the destination’s container port, not necessarily the host port published for browsers or other host clients.

For a Compose service named database that listens on PostgreSQL’s usual container port, an application container would normally target database:5432. Localhost:5432 would instead ask whether PostgreSQL is running inside the application container.

  1. 1Name the client and server containers and confirm they share a network.
  2. 2Resolve the server’s service name from inside the client container.
  3. 3Check that the server listens on its container interface and expected port.
  4. 4Test the service name and container port from the client container.
  5. 5Inspect published host ports only when the client actually lives on the host.

Common questions

Frequently asked questions

Should a container connect to the host using 172.17.0.1?

Do not assume that address. Bridge ranges and gateway addresses vary by platform and configuration. Prefer a supported host name or an explicitly configured host-gateway mapping, then verify it in the running environment.

Does EXPOSE make a container port reachable from the host?

No. EXPOSE documents intended ports and can be used by tooling, but it does not publish a host port by itself. Use an explicit port mapping when host access is required.

Why can one container not reach another on localhost?

They normally have separate network namespaces and loopback interfaces. Use the destination container’s service name on a shared Docker network.

Keep learning

Sources and next steps