Customize Docker network

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:  <--> [host machine] eth0: / docker0: <--> [containers] eth0:

The host machine has 2 IP addresses. One is, which connects to a gateway interface eth3 with IP address through its physical interface eth0. The other is, which is assigned to the Docker Ethernet bridge interface docker0. The four Docker containers have addresses from to

By default, Docker configures bridge interface docker0 with IPv4 address We need to change it to 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:

# /etc/sysconfig/docker
# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--bip= --iptables=false'
# ...

In this file, the --bip= option tells Docker to set up bridge interface with IPv4 address, and --iptables=false to disallow Docker to insert iptables rules automatically.

Restart your Docker service, then start a container:

$ systemctl restart docker # systemd OS
$ service docker restart # other OS
$ docker run -ti --rm --net=none --name my_container centos:7 /bin/bash # 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:

# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever

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:

PID=`docker inspect -f '{{.State.Pid}}' my_container`

Then, create a peer of virtual network interfaces A and B, then bind the A end to the bridge, and bring it up:

$ ip link add A type veth peer name B
$ brctl addif docker0 A
$ ip link set A up

Next, place B inside the container’s network namespace, and rename to eth0, and activate it with IP Follow similar steps to configure networks for other containers by replacing IP addresses with -

$ ip link set B netns $PID
$ ip netns exec $PID ip link set dev B name eth0
$ ip netns exec $PID ip link set eth0 address 12:34:56:78:9a:bc
$ ip netns exec $PID ip link set eth0 up
$ ip netns exec $PID ip addr add dev eth0
$ ip netns exec $PID ip route add default via

Lastly, add a static route on your gateway to forward address range to your host machine:

$ ip route add via dev eth3

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.

Old Posts Migrated

Posts in my old blog, which hasn't been maintained for serveral years, has been successfully migrated to this new room!… Continue reading