Use bridge networking instead of NAT in Docker Desktop on Windows

Hi everyone,

I have a web application that uses Docker. My containers are configured to run on a custom bridge network: 172.19.1.0/24, with 172.19.1.1 as the gateway.

When I deploy the application on a Linux server, it seems that the containers are properly bridged to the host network. For example, the container running my Nginx web server receives HTTP requests with the real IP addresses of the clients — which is what I want.

However, when I deploy the same application on my Windows 11 machine using Docker Desktop (and so WSL2), it seems that the containers are NATed through the host. As a result, my Nginx container sees all incoming requests coming from the gateway IP (172.19.1.1) instead of the real client IPs.

At the moment, I’m working around this by placing a reverse proxy (Traefik) in front of the app, but this setup is not ideal for my needs.

Is there a way to bridge the container network to the host in Docker Desktop for Windows, so that containers can see the real client IPs?

Thanks in advance!

As the WSL2 utility vm itself already runs in a NATed network, the docker engine that runs in the docker desktop distribution has no chance to get the real ip.

Thank your very much for your feedback!
After a quick search, it seems there are some hacks to bridge WSL network using Hyper-V. Will try that.
But ok, I’ve noticed that the problem isn’t due to docker desktop. :grin:

If it’s really just about the source ip, you could try if leveraging the proxy protocol solves that issue for you: one traefik instance on the Windows host, one traefik inside a container that routes the traffic to the target container.

Note: you can use traefik interchangeable with any other reverse proxy that supports the proxy protocol.

Let me check if I’ve correctly understood your idea…

  • The client has IP 192.168.0.10.
  • The Windows host has:
    • IP 192.168.0.254
    • Traefik listening on port 80
    • My Docker stack
  • My Docker stack includes:
    • A Traefik container listening on port 81 (exposed on the host)
    • An Nginx container listening on port 80 (not exposed on the host)

So…

  • The client (192.168.0.10) sends an HTTP request to 192.168.0.254.

  • This request is received by the Windows Traefik, then forwarded to 127.0.0.1:81 using the proxy protocol.

  • The request is then handled by the Docker Traefik, which forwards it to the Nginx web server.

  • The Nginx web server must be configured with real_ip_header proxy_protocol;.

  • The response from the web server to the client is sent back through the WSL NATed network.

Did I get that right?

After writing this, I’m not really sure what the purpose of the Docker Traefik is. Can’t I just configure the Windows Traefik to forward requests directly to the Nginx container?

In my assumption there was no nginx involved. Since nginx already “speaks” the proxy protocol, of course you can.