Macvlan, transparent, and host netowork types?

I was just wondering if anybody has found a way to get host, macvlan, or transparent type networking to work on Windows. Many things require an IP on the host network and fail for one reason or another without it.

I have been scouring the interwebs for help with this for days. I have found a few posts about creating a bridge in the host windows network settings between the hyper-v interface and the docker host interface, but I’m still not sure how to implement that in the inside when building images/containers.

I know wsl2 now has bridging support, but it seems Docker still hasn’t updated to use it for some reason.

Thoughts? Ideas?

Thanks for stopping by!

1 Like

You might want to read this blog post:
WSL Mirrored Mode Networking in Docker Desktop 4.26.0 - DEV Community.

1 Like

I just made some test with WSL2 and Docker-CE in Ubuntu (without Docker-Desktop).

My WSL2 version:

C:\Users\....>wsl --version
WSL-Version: 2.1.4.0
Kernelversion: 5.15.146.1-2
WSLg-Version: 1.0.60
MSRDC-Version: 1.2.5105
Direct3D-Version: 1.611.1-81528511
DXCore-Version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows-Version: 10.0.22631.3235

My .wslconfig:

[wsl2]
networkingMode=mirrored
dnsTunneling=true
[experimental]
useWindowsDnsCache=true
bestEffortDnsParsing=true
hostAddressLoopback=true

Note: I am not sure if any of the experimental features are required.

My host ip: 192.168.199.188
The WSL2 ip (eth1): 192.168.199.188

Test1: host network

start container attached to host network (=no network namespace isolation)

docker run -d --rm --name nginx  --network=host nginx

Result

The container can be accessed from Windows by using the Windows host ip 192.168.199.188 → host mode works

Cleanup

docker stop nginx

Test2: macvlan network

setup

I run following script snippet to create the macvlan interface and a shim bridge to bypass the security limitation that prevents macvlan parent<>child communication (must be run as root!).

The first three variables will have different values for you and must be modified to match your subnet and desired range for the macvlan network:

NETWORK_CIDR=192.168.199.0/24
IP_RANGE_CIDR=192.168.199.32/27
GATEWAY_IP=192.168.199.1
PARENT_INTERFACE_NAME=eth1

docker network create -d macvlan \
  --subnet=${NETWORK_CIDR} \
  --ip-range=${IP_RANGE_CIDR} \
  --gateway=${GATEWAY_IP} \
  --aux-address="${HOSTNAME}=${IP_RANGE_CIDR%/*}" \
  -o parent=${PARENT_INTERFACE_NAME} mymacvlan

ip link add macvlan-shim link ${PARENT_INTERFACE_NAME} type macvlan mode bridge

ip addr add "${IP_RANGE_CIDR%/*}/32" dev macvlan-shim
ip link set macvlan-shim up

ip route add ${IP_RANGE_CIDR} dev macvlan-shim

start the container attached to macvlan network

docker run -d --rm --name nginx --network mymacvlan --ip 192.168.199.33 nginx 

Test inside WSL2 distro:

root@matebook:~#  curl 192.168.199.33
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Test from Windows:

 curl 192.168.199.33
curl: (28) Failed to connect to 192.168.199.33 port 80 after 21048 ms: Couldn't connect to server

Result

The macvlan chiled ip can be accessed inside the WSL2 distro, but not from the host. For whatever reason the ping operation works for 192.168.199.32 and 192.168.199.33, but also for 192.168.199.34 which is not assigned to anything in my network. → Not working!

cleanup

docker stop nginx
docker network rm mymacvlan

This is necessary, as a gateway can only be assigned to a single container network.

Test3: ipvlan network

setup

I run following script snippet to create the ipvlan interface and a shim bridge(?) to bypass the security limitation that prevents ipvlan parent<>child communication (must be run as root!).

The first three variables will have different values for you and must be modified to match your subnet and desired range for the ipvlan network:

NETWORK_CIDR=192.168.199.0/24
IP_RANGE_CIDR=192.168.199.32/27
GATEWAY_IP=192.168.199.1
PARENT_INTERFACE_NAME=eth1

docker network create -d ipvlan \
  --subnet=${NETWORK_CIDR} \
  --ip-range=${IP_RANGE_CIDR} \
  --gateway=${GATEWAY_IP} \
  --aux-address="${HOSTNAME}=${IP_RANGE_CIDR%/*}" \
  -o parent=${PARENT_INTERFACE_NAME} \
  -o ipvlan_mode=l2 \
  -o ipvlan_flag=bridge \
   myipvlan

ip link add ipvlan-shim link ${PARENT_INTERFACE_NAME} type ipvlan mode l2

ip addr add "${IP_RANGE_CIDR%/*}/32" dev ipvlan-shim
ip link set ipvlan-shim up

ip route add ${IP_RANGE_CIDR} dev ipvlan-shim

start the container attached to macvlan network

docker run -d --rm --name nginx --network myipvlan --ip 192.168.199.33 nginx 

Test inside WSL2 distro:

same result as macvlan

Test from Windows:

same result as macvlan

Result

same result as macvlan

cleanup

docker stop nginx
docker network rm myipvlan

Final thoughts

It seems like macvlan and ipvlan are not working in mirrored mode, which makes sense as mirrored seem not to act like a bridge. But let’s assume for a minute mirrored mode bridges the collision domain as well, then maybe firewall rules prevent the access? I haven’t tried other ipvlan modes and flags, or to tinker around with firewall rules.

Unless what you are looking for can be made working in WSL2, I doubt that Docker Desktop will be able to work around the limitations. But according to the blog post, it looks like Docker Desktop found an alternative solution that kind of acts like ipvlan/macvlan and even provides dns names for the containers that can be resolved from the Windows host.

Note: Docker Desktop already takes care of forwarding traffic from the host lan ip to the container, so host mode is not so easy to test. the first part is irrelvant to testing the host mode, and testing it is not any different in Docker-Docker than it is for Docker-CE in a WSL2 distro.

I just checked whether the docker desktop utility vm has the mirrored eth1 interface as well:

docker run -it --rm --privileged --pid=host justincormack/nsenter1
ip a
# then check the output for eth1 or the Windows host ip

To my surprise it does not exist.

Furthermore, I am not able to reproduce what the blog post announced with Docker Desktop v4.28.0.