Containers are certainly one of the hottest topics today. This year, Microsoft partnered with Docker to bring the Docker platform to Windows Server 2016 by introducing Windows/Hyper-V containers as well as native Docker engine support. That's a huge step for overall container technology to push them through to production in enterprise organizations.
There are many things to consider when implementing containers. Conversation usually starts with applications.
- Which application is a good fit for containers – monolithic, micro-services, stateless or stateful?
- Service discovery?
- What about security patching?
- Container monitoring?
- Orchestration tools?
Given the simplicity of container technology, it's now much easier to deal with underlying infrastructure and fabric to run containers. Actually, containers don't care too much about infrastructure as they keep all processes inside the container, isolated from external threats.
But for enterprise level deployments and production environments, network settings are something you may want to take into account. How do containers talk to each other? What type of network setup should we have for containers? How can you provide public access to containers or configure a network to allow containers to talk to each other within a private network?
Microsoft leverages similar Hyper-V networking components (vSwitch, vNIC) in order to provide the network layer to containers. Once you enable the container feature on a Windows box, a new Hyper-V Virtual Ethernet Adapter will be created and all containers will have a vNIC connected to vSwitch.
Viewing NAT configuration ^
After you install the containers feature and the Docker package, a default network called "NAT" will be created. You can retrieve container networks using the Docker CLI or the PowerShell Get-ContainerNetwork cmdlet.
docker network ls
NAT is the same network as "bridge0" in Linux container environments. By default, it's created for each container host with an IP Prefix of 22.214.171.124/12. If you don't specify any additional network parameter/flag while running containers, each container will be attached to this network, and the Docker engine provides a free IP address available on the NAT network to containers. The default NAT network also supports port forwarding from container host to internal containers. For example, you can simply run SQL Server Express in a container by providing the "p" flag so that specified port numbers will be mapped from host to container. In this way, I can easily access my database from an external network.
Let's check the networking configuration for a container. In order to run commands inside the container, you can use docker exec. The following command will run PowerShell inside my container:
docker exec -it ac0722b09f2e powershell
As can be seen, the container has a virtual network adapter (vNIC) connected to my virtual switch and it's configured with an IP address from the default NAT network prefix.
All containers have a configuration file that allows you to check each and every detail including networking. This file can be found under c:\ProgramData\Docker\Containers\<containerID>
The config.v2.json file has all the configuration details for this container:
If you want to get more information for a particular container network, you can use the "docker network inspect <networkName>" command.
This shows available container networks, all connected containers, and network resources.
On the above output, you can easily see that no containers are attached to this network yet. If you run some containers and don't specify any custom network flags, these containers will be attached to the NAT network automatically.
After starting some containers, you can try to inspect the same network again to see the attached containers.
Connect and disconnect NAT ^
If you recall from the first command (docker network list), there was also one additional network called "none." You can connect your existing containers to another available network using docker disconnect/connect commands. The following commands switch my existing container network from "nat" to "none."
docker network disconnect nat <containerID>
docker network connect none <containerID>
If you check the config.json file again, you will see that the networkID and endpointID values are now empty.
Configuring NAT ^
You may want to change the IP prefix of the default NAT network so that the engine will assign private IP addresses to containers from the range you specified.
Under the C:\ProgramData\Docker\config\ directory you can create the daemon.json file which is actually the Docker config file for the Docker service on your Windows host. It doesn't show up automatically when you install the container feature, so you need to create that file manually in most cases.
In the current version of Windows containers, only following options are supported in Docker configuration files:
By changing the values for those options, you can configure your Docker environment as per your requirements. You only need to add the desired options to the configuration file and remove unused options. For our example, we want to change the IP prefix of the default NAT network.
<"fixed-cidr": ""> is the option which will create the default NAT network with the IP prefix you specified.
In order to play with the Docker configuration file, you need to stop the Docker service first.
Then you need to remove the existing NAT network using native PowerShell commands:
Get-ContainerNetwork | Remove-ContainerNetwork
Now you can create the daemon.json file and make the desired changes. Below, I just added a section to the configuration file:
"fixed-cidr" : "192.168.10.0/24"
And finally, you can start the Docker service again.
If you use the Get-ContainerNetwork or docker network inspect command, you can see that a new NAT network is created by the Docker service with the IP prefix we specified in configuration file:
Hereafter, all created containers will pick an IP address from this custom NAT network unless you specify custom network flags in the run command.
In the second part, we are going to look at creating custom NAT drivers and additional network drivers you can implement in Windows containers.