The standard setup for Windows Docker containers is to connect new containers to a NAT network. For more information see Microsoft Docs, but basically it means that a new container gets an IP address from an internal network which is only reachable form the host (your laptop or VM where the container is running). That works fine but it means that you need to call the container by IP address, not by name, which is not really convenient. To work around that I have created a small (of course containerized) tool that allows you to reach the containers by name.
The tool listens for starting containers and writes their IP addresses and names to the hosts file on Windows. That file is always checked first when a network connection on Windows tries to find out the IP address for a hostname, so should work with every browser or other tool that needs to make a connection to your container. Running it is very simple:
docker run -v \\.\pipe\docker_engine:\\.\pipe\docker_engine -v c:\Windows\System32\drivers\etc:c:\driversetc -d tobiasfenster/windows-hosts-writer:1809
It gives the container access to the Docker engine so that it can listen for container starts (and stops) and also to the hosts file which is located in c:\Windows\System32\drivers\etc
. With that in place name resolution for your containers is as easy as you can see in the following clip (click to start). The first step is running a container in the background which just pings localhost endlessly so that it keeps running. The second step then is to show how name resolution works by pinging the first container using its hostname.
I’ve created a very small .NET Core 2.2 console application using a library called Docker.DotNet to interact with the Docker engine API. The library works quite well although it seems to be not very actively maintained1. My implementation can be found here but it really is quite simple with probably the only interesting part as follows:
var containerEventsParams = new ContainerEventsParameters() { Filters = new Dictionary<string, IDictionary<string, bool>>() { { "event", new Dictionary<string, bool>() { { "connect", true }, { "disconnect", true } } }, { "type", new Dictionary<string, bool>() { { "network", true } } } } }; GetClient().System.MonitorEventsAsync(containerEventsParams, progress, default(CancellationToken)).Wait();
Not the most intuitive API in my opinion, but it works. Whenever a container connects to or disconnects from a network, which happens on start and stop of a container. It then calls a progress handler which in turn calls a method that gets the IP address of the container and writes it to the hosts file. The implementation is quite straight forward and you can find it here if you want to take a look.
As further improvements I plan to implement a check of all running containers when the helper container starts so that it can remove stale entries from the hosts file and also populate it with any running container if they were started while the helper wasn’t running. Or if you like the tool and want to improve it that way or with any other feature you think would help, just create a PR.