xand.es

Assign IP address to docker container

Many times when working with docker containers I feel the need of assigning a known beforehand IP address to a container. This is a huge advantage if you want to control the network access to and from a container with a tool like iptables. However, current docker version (1.11.1) does not allow this operation out of the box, but there is an official way of achieving this. Thanks to docker network command a user may create a fully customizable network and connect a container to it. You may find full information at the official Docker site, here.

I will start with a clean docker installation on a test vagrant machine (Ubuntu Trusty). After installing docker, as usual, you may see docker0 network interface. This a default bridging interface. I will follow the documentation and create an isolated network using the same subnet, addresses and names.

So the first step is to create a new network:


$ docker network create -d bridge --subnet 172.25.0.0/16 isolated_nw

This network will allow me to use a 172.25.0.1 - 172.25.255.254 address range. If I run ifconfig now I will see that a new interface is created. In my case, docker calls it br-98446a2a4f1f. Just to be sure I reboot my machine to see if this network persists across reboots and it does.

Now I want to start nginx container with 172.25.0.2 address, I can do it with the following command:


$ docker run --net=isolated_nw --ip=172.25.0.2 -d --name=my_nginx_01 nginx

If I get inside the container and run ip addr command I will see that the assigned IP address is, in fact, the requested one:


root@597d1056bc32:/# ip addr
7: eth0:  mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:19:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.25.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe19:2/64 scope link
       valid_lft forever preferred_lft forever

Now, I will start another container just to check the connectivity between them:


$ docker run --net=isolated_nw --ip=172.25.0.3 -d --name=my_nginx_02 nginx

So, if I get inside a second container I'm able to perform ping and telnet with the first one:


root@47f62e6951db:/# ping 172.25.0.2
PING 172.25.0.2 (172.25.0.2): 56 data bytes
64 bytes from 172.25.0.2: icmp_seq=0 ttl=64 time=0.253 ms
64 bytes from 172.25.0.2: icmp_seq=1 ttl=64 time=0.103 ms
64 bytes from 172.25.0.2: icmp_seq=2 ttl=64 time=0.140 ms
--- 172.25.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.103/0.165/0.253/0.064 ms

root@47f62e6951db:/# telnet 172.25.0.2 80
Trying 172.25.0.2...
Connected to 172.25.0.2.
Escape character is '^]'.
Connection closed by foreign host.

Time to check that linking between containers also works, I will start my containers this way:


$ docker run --net=isolated_nw --ip=172.25.0.2 -d --name=my_nginx_01 nginx
$ docker run --net=isolated_nw --ip=172.25.0.3 --link my_nginx_01:my_nginx_01 -d --name=my_nginx_02 nginx

Then, if I connect to my_nginx_02 container I will be able to ping and telnet my_nginx_01 host.


root@6e36ce623842:/# ping my_nginx_01
PING my_nginx_01 (172.25.0.2): 56 data bytes
64 bytes from 172.25.0.2: icmp_seq=0 ttl=64 time=0.161 ms
64 bytes from 172.25.0.2: icmp_seq=1 ttl=64 time=0.173 ms
--- my_nginx_01 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.161/0.167/0.173/0.000 ms

root@6e36ce623842:/# telnet my_nginx_01 80
Trying 172.25.0.2...
Connected to my_nginx_01.
Escape character is '^]'.
Connection closed by foreign host.

As you can see my_nginx_01 resolves to the IP address assigned during the startup. With this configuration, you may be able to control your security perimeter using FORWARD chain in your iptables configuration.