Docker is an awesome software which makes use of Linux container to package dependencies for an application and isolate its runtime environment from the host machine. By default, Docker will set up an isolated private network and adopt Network address translation (NAT) technology for forwarding incoming traffic to corresponding container. But sometimes we want to set up our own Docker network.
A few days ago, I was going to run several separated Bind DNS services on a single host. Some of them are recursive servers while others are authoritative servers. Traditionally, we need to bind these services to different addresses on the same host, or create virtual machines for every Bind instance.
I chose Docker for this kind of deployment. The difficulty is how to expose the whole network of these containers
to the outside network instead of using NAT technology, because it is very hard to maintain so many IP addresses on a single host machine.
We can use --net=none
option when starting a container to tell Docker not to configure its network automatically, which leaves us free to configure our own network.
Considering I have a host machine and 4 Docker containers. The host machine’s physical interface connects to a router that connects to an intranet.
[gateway] eth3: 10.3.0.1/24 <--> [host machine] eth0: 10.3.0.2/24 / docker0: 10.3.16.1/20 <--> [containers] eth0: 10.3.16.11/20-10.3.16.14/20
The host machine has 2 IP addresses. One is 10.3.0.2/24
, which connects to a gateway interface eth3
with IP address 10.3.0.1/24
through its physical interface eth0
.
The other is 10.3.16.1/20
, which is assigned to the Docker Ethernet bridge interface docker0
. The four Docker containers have addresses from 10.3.16.11/20
to 10.3.16.14/20
.
By default, Docker configures bridge interface docker0
with IPv4 address 172.17.42.1/16
. We need to change it to 10.3.16.1/20
in this deployment.
To supply a different IP address for docker0
, We need to edit Docker upstart configuration file. This file is usually located at /etc/sysconfig/docker
for Fedora/RHEL/CentOS or /etc/default/docker
for Debian/Ubuntu.
Here is a resonable configuration:
In this file, the --bip=10.3.16.1/20
option tells Docker to set up bridge interface with IPv4 address 10.3.16.1/20
, and --iptables=false
to disallow Docker to insert iptables rules automatically.
Restart your Docker service, then start a container:
This will start a CentOS 7 container named my_container
. Option --net=none
tells Docker not to set up container network.
Issuing ip addr
in this container will find that there are no Ethernet interfaces configured:
As Docker uses Linux container to isolate environment, we should set up a container network through the host machine. These instructions are adapted from official Docker documentation.
Firstly, use docker inspect
command to find out the container process ID:
Then, create a peer of virtual network interfaces A
and B
, then bind the A end to the bridge, and bring it up:
Next, place B inside the container’s network namespace, and rename to eth0, and activate it with IP 10.3.16.11/20
.
Follow similar steps to configure networks for other containers by replacing IP addresses with 10.3.16.12/20
- 10.3.16.14/20
.
Lastly, add a static route on your gateway to forward address range 10.3.16.0/24
to your host machine:
In addition, I wrote a script called Dockernet in order to finish these steps in a very simple way. You can check out my code if you like.