Docker Networking

One of the most transparent/hidden item of Docker is related to network world but, as we will see, there’s much time to spend behind this argument.

As we seen into the previous articles, when we create a new container in automatic he receives an IP address to expose services, when required, through NAT. What happen when we want make more secure our network and improve the Docker infrastructure?

After the first Docker deploy, a new network interface is created with IP 172.17.0.0/12 (172.16.0.0/12 in Windows). This range allows to create many containers, without take care about this, but as you can imagine all of these are in the same box because the network is the same.

Ok, Docker is not a classic installation like a server with IIS or Apache and this is a great point for security (escalation is very complicated and there’s no way to open a SSH session to the remote container); so why I should care about the networking?

Simple, the idea is add another layer to increase security and isolate some environment from public network.

Driver

These are the network driver available in Windows:

Network Address Translation (NAT) – each container will receive an IP address from an internal, private IP prefix. Port forwarding / mapping from the container host to container endpoints is supported.

Transparent – each container endpoint is directly connected to the physical network. IPs from the physical network can be assigned statically or dynamically using an external DHCP server.

Overlay – when the Docker engine is running in swarm mode, overlay networks, which are based on VXLAN technology, can be used to connect container endpoints across multiple container hosts. Each overlay network that is created on a Swarm cluster is created with its own IP subnet, defined by a private IP prefix.

L2 Bridge – each container endpoint will be in the same IP subnet as the container host. The IP addresses must be assigned statically from the same prefix as the container host. All container endpoints on the host will have the same MAC address due to Layer-2 address translation.

In Linux we have these drivers:

Bridge – each container will receive an IP address from an internal, private IP prefix. Port forwarding / mapping from the container host to container endpoints is supported.

Overlay – when the Docker engine is running in swarm mode, overlay networks, which are based on VXLAN technology, can be used to connect container endpoints across multiple container hosts. Each overlay network that is created on a Swarm cluster is created with its own IP subnet, defined by a private IP prefix.

MACVLAN – containers are addressed with routable IP addresses that are on the subnet of the external network. As a result of routable IP addresses, containers communicate directly with resources that exist outside a Swarm cluster without the use of NAT and port mapping.

In this article, I will use the Bridge mode, the most common scenario with mono-host. I wrote Bridge and not NAT because in this moment there’s no way to configure multi-interface with many IP addresses; so, if you want isolate your Container on Windows is necessary deploy another server.

BTW there’s a workaround to achieve the result, with the partitioning of default range (172.16.0.0/12). This is the PowerShell cmdlet:

docker network create -d nat –subnet=172.16.0.0/24 –gateway=172.16.0.1 nat-lan-01

docker network create -d nat –subnet=172.16.1.0/24 –gateway=172.16.1.1 nat-lan-02

NB: this task must be provided before create any kind of container

Network Creation in Linux

To create a new network bridge is necessary run this command:

docker network create –driver bridge –subnet 192.168.0.0/24 –gateway 192.168.0.1 –ip-range 192.168.0.128/25 nat-lan-01

What I’m doing is add a new network with NAT mode (bridge) with a subnet 192.168.0.0 at 24bit mask, where the gateway (Container Host) have the first IP; all the new container will be created with IP range from .128 to .254.

To see all the network interface you can use the command: docker network ls

Once the network is ready, you can create a new container with this syntax:

docker run –name lab-web02 -p 801:80 –hostname “lab-web02” –network nat-lan-01 ubuntu

In case you would connect a new network to an existing container, this is the command to use:

docker network connect nat-lan-01 lab-web01

How I can check all the connection established to a specific network? Simple, with the command: docker network inspect nat-lan-01. The result will be similar like this one:

[
    {
        "Name": "nat-lan-01",
        "Id": "288142ee264c96f722be3a7fd60837ea3ce19387a2cfe45efc3f7f6a858bd39c",
        "Created": "2017-03-04T19:04:45.4562786+01:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/24",
                    "IPRange": "192.168.0.128/25",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "ece751a19c8bda066044fa496474f57926fb2c2947c2e962f4d6cede8a53fd08": {
                "Name": "lab-web02",
                "EndpointID": "635f99c86a97a9b03eeb6b37477002ad31cfb62f144ec77b2b5740607d0498b5",
                "MacAddress": "02:42:c0:a8:00:80",
                "IPv4Address": "192.168.0.128/24",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Isolation and Sub-Connection

Create a new network is useful not only for security but also to have a dedicated connection between some containers.

As we can see from the image 1, it is possible create a network to connect two containers to allow communication of a specific service; for example, between a front-end and a back-end we can use a dedicated network.

In this case could be better set a static IP address to avoid problems from front-end. This task is possible with the commands:

docker network create –driver bridge –subnet 192.168.100.0/24 –gateway 192.168.100.1 –ip-range 192.168.100.128/25 net01-sql-lan

docker run –name appsrv01 -p 801:80 –hostname ” appsrv01 ” –network nat-lan-01 ubuntu-apache

docker run –name mysql01 –hostname ” mysql01 ” –network nat-lan-01 ubuntu-mysql

docker network connect net01-sql-lan appsrv01 –ip 192.168.100.130

docker network connect net01-sql-lan mysql01 –ip 192.168.100.128

Specify an IP address is a great idea to create specific firewall rules or many other security tricks to reduce the attack surface.

Conclusion

Networking in Docker is not simple but is an important part of the ecosystem. I gave you only the main concept because, as I said at beginning, there’s an entire world around network; for example, you could also create a new interface with VLAN or use a tag to simplify the deployment.

Get Started

You want know more? Check these links!

#DBS