Bridge with Docker for Windows

I’m trying to run a Bebop2 using ROS and Bebop_autonomy from inside a container. When I run the container on Linux with --network=host, everything works correctly and there are no problems. However, when I try to run it on my windows machine, I never receive any of the ACK packets back when I start bebop_autonomy. I’ve attempted changing the switch in the Hyper-V manager, but I’m just not understanding the technology correctly I think. I believe I need a bridged network so that the container can “connect” to the Bebop2’s wifi hotspot through my laptop’s NIC and have the packets forward through. People say Bebop_autonomy runs in a VM with a bridged network, but from what I’ve read in the last few days, Docker is already running one.

Any insight would be helpful, as the Docker container is useless on windows if I can’t get it to use the host machine’s network correctly.

I ended up creating another switch in the Hyper-V manager, telling it to only use an external wifi-adapter. I connected that adapter to the bebop, and it seemed to work correctly. There has to be an easier way though.

Hey there! I’ve also been struggling with this issue, and can’t for the love of my life figure out why --net=host won’t work in windows. Could you be a bit more specific on how you did to connect a new Hyper-v switch to a container? Or did you change from “dockerNAT” to the new one? Any help would be much appreciated!

I actually filmed a video tutorial for a project I’m working on. This is meant to help someone go from nothing to being able to use all of the work we’ve done so far. Setting Up Docker for Windows Watch from 2:12 until around 4:20.

This might not be exactly what you need, but it works for our use case. Typing “ipconfig” in the powershell will show you that the external network isn’t even recognized by the computer, while typing ip addr inside the container will display it correctly. This means only your containers are using the network that adapter is connected to.

Incredibly, I could not find any answer of how to do it anywhere on the web. First I thought Docker should have a configuration for it or a different process to create and use custom networks on Windows, but the truth is that Docker has nothing to do with this issue. It is merely a matter of Windows settings.

What I am saying is that there is a much simpler way to use a “bridged” networked container (Linux type) in Windows without any “dirty trick”, “special driver” or “hack” as many crazy answers I found suggested.

Here is how to do it right: First, create a custom network on Docker exactly as if you were doing it on Linux. Example:

docker network create -d bridge --subnet 172.168.0.0/16 mynet

Once you do that in Linux, your new network is automatically bridged to your NIC, allowing you to create any container with the keywords “--network mynet --ip 172.168.0.1” (where IP can be any IP in the range of the network you created). It will define your container as part of the network and set it to use the specified IP address, allowing you to create and simulate process isolation, test intra-network processes, use custom local domains via host file, etc.). In Windows, however, it simply is not possible because the Hyper-V doesn’t offer Bridged option for Linux containers, which simply mutes the Bridge element created by docker network command. It will be there, but will behave as a NIC without a cable connected to it (no communication in any direction).

To connect the newly created Docker Bridge in Windows is simpler than you may think. Basically, every time you want to set a container to respond from your custom network, using a custom IP, the specific IP address must exist in the Docker Network Adapter, commonly named as vEthernet (DockerNAT). Here how to do it:

1 ) Go to Control Panel -> Network and Internet -> Network Connections
2 ) Right Click on vEthernet (DockerNAT) and select Properties
3 ) Select Internet Protocol Version 4(TCP/IPv4) and click Properties
4 ) Give to the adapter a static IP address that is valid on your current real network. Make sure the DNS is also valid so the container will be able to resolve domains on the Web
5 ) Once set, click Advanced, then click on Add and then enter the IP you want to include in the list. The Subnet mask should autofill as soon as you click on it, based on the IP address you’ve entered (of course, you can change it if needed). Repeat this process for every IP you intend to use. Each single IP you set for a container must exist in the list of IP Addresses of the Adapter. You can add as many IP’s you need, from the same or different networks. It will be used internally only to allow your computer to access the container using one of those specific IPs.

Once you complete this step, you can start using your custom network as if you were on Linux. No difference.

As an example, try installing the Portainer to run from your custom network. Here’s how:

First, create the require Portainer volume (step only needed on Windows):

docker volume create portainer_data

Then create the Portainer container using:

docker run -d -p 9000:9000 --name portainer --network mynet --ip 172.168.0.254 --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

Noticed the keywords --network and --ip? You can even set a custom local domain (for instance, docker.local) in the hosts file that points to the IP address 172.168.0.254 which will allow you to access the local Portainer via http://docker.local:9000 (or http://172.168.0.254:9000).

That’s it! You are done. All working exactly as it works on Linux. Have fun! :wink:

A very simple process that works flawlessly. No need to mess with the Hyper-V Manager configuration, add external devices or any other “hack”. Nothing more than the old and simple network configuration process that most people nowadays appear to have forgotten still exist. :sunglasses:

P.S.: I wonder why such information cannot be found anywhere in the Docker documentation or even in the official forums? :face_with_monocle:

3 Likes

This is awesome !
And I really think people should not forget simplicity and tradition methods of networking.
This indeed is valuable and informative.

Wish we had some discussion on the web using such lines.

Great work pal ! Appreciate it :wink:

You are my hero mate! I was stuck with this problem for 2 weeks and could not figure it out what the hell is wrong. I followed your steps and it worked on first go. Thanks allot.

But manually adding the IP needs to be done everytime the machine is restarted which is annoying.

Hi @bpunie,

I don’t understand when you say you need to “re-add the IP every time the machine reboots”. It is not the case for me or my team. I have implemented the same process in many places and it works flawlessly, and the configuration sticks. Can you describe your process? Most likely something is missing or different…

I will do my best to help you if I can.

Sorry, my bad. I was switching between Hyper-V and VirtualBox which means turning off Hyper-V to work with VirtualBox and when I turned Hyper-V back on. I had to add the IP again to DockerNAT. It should not happen if we just keep the Hyper-V running no matter how many times we restart. Thanks for getting back though. Your trick works sweet!

Hi again @bpunie,

There is actually another way to set the network environment to stick the configurations regardless of how many times you reset your Docker.

Basically, instead of adding the IPs to the vEthernet (DockerNAT), you may want to add them to the vEthernet (Default Switch). It should relieve you to switch from VirtualBox to Hyper-V as many times you want without having to re-create the network settings because Docker may in fact reset the vEthernet (DockerNAT) now and then after reboots and updates.

But, there are two important things to consider:

1 ) When you make changes in the vEthernet (Default Switch), leave the default Gateway blank (or you risk rendering your DNS resolution slow and tedious :grin:)
2 ) You will need to teach the Hyper-V (or the Docker container itself) how to pass network traffic through both environments (a technique known as “bridge” in Linux and as “NAT” in overall networking lingo).

There are two routes to achieve such result, which will depend on your specific needs:

A ) You can add a “NAT Private Virtual Switch” in the Hyper-V level, creating a direct communication layer in between the Windows Network Environment and the Hyper-V Environment (thus all containers under Hyper-V will be “bridgeable” to any Adapter you may have)
B ) You can add a “Virtual Network Adapter” in the Docker container under Hyper-V (which in my case is called MobyLinuxVM) and set its LAN Identification option as active.

The tie-breaker should be as follows: if you have other Virtual Machines created and directly managed by Hyper-V, you may want to take the route A, keeping the isolation of Hyper-V containers intact. On the other hand, if you will only use Docker and other external tools (such as VirtualBox) and not Hyper-V or Azure for your virtualization needs, the route B should be simpler to implement.

Here the “how to”:

Route A: Adding a “NAT Private Virtual Switch” in the Hyper-V level

1 ) Access the Hyper-V Manager
2 ) On the Actions panel find and click where it says “Virtual Switch Manager…
3 ) A new dialog will open. Click where it says “New virtual network switch”, select the option Private in the type of switch and click on Create Virtual Switch
4 ) A new Virtual Switch will be added to the end of the Virtual Switches List and some options will be available for you to adjust before saving it. Name it as you please (I simply called it “nat”), then make sure the option Private network is selected. Click OK to save it.

When you restart the Docker, by having a “nat” switch active, the Hyper-V environment network traffic will also pass through the Windows Network Environment, allowing you to define your own networks with custom IPs for the containers.

Route B: Adding a “Virtual Network Adapter” in the Docker container

1 ) Access the Hyper-V Manager
2 ) Click on “Hyper-V Manager” to see the Virtual Containers that are set in your Host
3 ) Right Click on the MobyLinuxVM and select “Settings…”. A new dialog will open. Click on Add Hardware. On the right portion of the dialog select Network Adapter and click in the button Add
4 ) The dialog will change and the configuration options for the new Network Adapter will show. Make sure you set the Virtual Switch as DockerNAT and enable the VLANID option. Click OK

Now just restart Docker so it can use the new network card and you should be OK switching it with VirtualBox without losing your configurations.

In fact, by doing that, most likely your network traffic could also be available for the VirtualBox machines, as far the network is properly set (IP ranges) and if you find a way to run both hypervisors simultaneously. :yum:

I hope it helps. Let me know if it worked for you. Have fun!

2 Likes

I am using Windows-11 home edition where, I use WSL-2 instead of hyper-v.
Can you please guide me how can we setup the bridge for WSL

1 Like

@sferrell615 posted a SO link that discusses how to use WSL2 in bridge mode (unreleated to docker’s bridge network):