Nginx running in Docker, reverse proxying to localhost outside of Docker

By design, applications listening on localhost (127.0.0.1/8 or ::1/128) are accessible only locally on the same machine. Or, strictly speaking, from the same network namespace. By default, Docker containers have their own network namespace, which comes with another, separate instance of localhost.

So with default Docker networking what you want is not possible: a container cannot connect to the host’s localhost.

Docker also supports a special networking mode: host networking. If you specify this when launching a container, it will not be put in a separate network namespace but instead use the host network namespace. The host’s and container’s localhost will be the same. However, there are implications:

  • Port mappings will not be effective
  • You need to take care not to use a port twice
  • Host networking cannot be mixed with links

Depending on your setup, nginx losing access to other containers could not be acceptable.

You could instead use something like socat to make the port accessible to Docker containers:

docker run -d --restart=always --network=host alpine/socat TCP4-LISTEN:4001,fork,reuseaddr,interface=docker0 TCP4-CONNECT:localhost:4001

From your nginx container, you could then reach the host at 172.17.0.1 with default networking.

You can also try adding --add-host=host.docker.internal:host-gateway to the nginx container invocation to get a DNS name (host.docker.internal) that would then always work no matter the configuration. This only works in very recent versions of Docker.