Docker provides hostname and DNS configurations for each container without us having to build a custom image. It overlays the /etc
folder inside the container with virtual files, in which it can write new information.
This can be seen by running the mount
command inside the container. Containers receive the same resolv.conf
file as that of the host machine when they are created initially. If a host's resolv.conf
file is modified, this will be reflected in the container's /resolv.conf
file only when the container is restarted.
In Docker, you can set DNS options in two ways:
docker run --dns=<ip-address>
DOCKER_OPTS="--dns ip-address"
to the Docker daemon fileYou can also specify the search domain using --dns-search=<DOMAIN>
.
The following figure shows a nameserver being configured in a container using the DOCKER_OPTS
setting in the Docker daemon file:
The main DNS files are as follows:
/etc/hostname
/etc/resolv.conf
/etc/hosts
The following is the command to add a DNS server:
# docker run --dns=8.8.8.8 --net="bridge" -t -i ubuntu:latest /bin/bash
Add hostnames using the following command:
#docker run --dns=8.8.8.8 --hostname=docker-vm1 -t -i ubuntu:latest /bin/bash
Packets can only pass between containers if the ip_forward
parameter is set to 1
. Usually, you will simply leave the Docker server at its default setting, --ip-forward=true
, and Docker will set ip_forward
to 1
for you when the server starts up.
To check the settings or to turn IP forwarding on manually, use these commands:
# cat /proc/sys/net/ipv4/ip_forward 0 # echo 1 > /proc/sys/net/ipv4/ip_forward # cat /proc/sys/net/ipv4/ip_forward 1
By enabling ip_forward
, users can make communication possible between containers and the external world; it will also be required for inter-container communication if you are in a multiple-bridge setup. The following figure shows how ip_forward = false
forwards all the packets to/from the container from/to the external network:
Docker will not delete or modify any pre-existing rules from the Docker filter chain. This allows users to create rules to restrict access to containers.
Docker uses the docker0
bridge for packet flow between all the containers on a single host. It adds a rule to forward the chain using IPTables in order for the packets to flow between two containers. Setting --icc=false
will drop all the packets.
When the Docker daemon is configured with both --icc=false
and --iptables=true
and docker run
is invoked with the --link
option, the Docker server will insert a pair of IPTables accept rules for new containers to connect to the ports exposed by the other containers, which will be the ports that have been mentioned in the exposed lines of its Dockerfile. The following figure shows how ip_forward = false
drops all the packets to/from the container from/to the external network:
By default, Docker's forward
rule permits all external IPs. To allow only a specific IP or network to access the containers, insert a negated rule at the top of the Docker filter chain.
For example, using the following command, you can restrict external access such that only the source IP 10.10.10.10
can access the containers:
#iptables –I DOCKER –i ext_if ! –s 10.10.10.10 –j DROP
Following these steps to restrict SSH access from one container to another:
c1
and c2.
For c1
, use the following command:
# docker run -i -t --name c1 ubuntu:latest /bin/bash
The output generated is as follows:
root@7bc2b6cb1025:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:05 inet addr:172.17.0.5 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: 2001:db8:1::242:ac11:5/64 Scope:Global inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:7 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:738 (738.0 B) TX bytes:696 (696.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
For c2
, use the following command:
# docker run -i -t --name c2 ubuntu:latest /bin/bash
The following is the output generated:
root@e58a9bf7120b:/# ifconfig eth0 Link encap:Ethernet HWaddr 02:42:ac:11:00:06 inet addr:172.17.0.6 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: 2001:db8:1::242:ac11:6/64 Scope:Global inet6 addr: fe80::42:acff:fe11:6/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:648 (648.0 B) TX bytes:696 (696.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
We can test connectivity between the containers using the IP address we've just discovered. Let's see this now using the ping
tool:
root@7bc2b6cb1025:/# ping 172.17.0.6 PING 172.17.0.6 (172.17.0.6) 56(84) bytes of data. 64 bytes from 172.17.0.6: icmp_seq=1 ttl=64 time=0.139 ms 64 bytes from 172.17.0.6: icmp_seq=2 ttl=64 time=0.110 ms ^C --- 172.17.0.6 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.110/0.124/0.139/0.018 ms root@7bc2b6cb1025:/# root@e58a9bf7120b:/# ping 172.17.0.5 PING 172.17.0.5 (172.17.0.5) 56(84) bytes of data. 64 bytes from 172.17.0.5: icmp_seq=1 ttl=64 time=0.270 ms 64 bytes from 172.17.0.5: icmp_seq=2 ttl=64 time=0.107 ms ^C --- 172.17.0.5 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.107/0.188/0.270/0.082 ms root@e58a9bf7120b:/#
openssh-server
on both the containers:#apt-get install openssh-server
DOCKER_OPTS="--icc=false --iptables=true"
to the default Dockerfile of the host machine. This option will enable the iptables firewall and drop all ports between the containers.By default, iptables
is not enabled on the host. Use the following command to enable it:
root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 #service docker stop #vi /etc/default/docker
#DOCKER="/usr/local/bin/docker"
DOCKER_OPTS
to modify the daemon's startup options:#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4" #DOCKER_OPTS="--icc=false --iptables=true"
# service docker start
iptables
:root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED, ESTABLISHED ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED, ESTABLISHED ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 DROP all -- 0.0.0.0/0 0.0.0.0/0
The DROP
rule has been added to iptables on the host machine, which drops a connection between containers. Now you will be unable to SSH between the containers.
--link
parameter, with the help of following steps:sshserver
:root@ubuntu:~# docker run -i -t -p 2222:22 --name sshserver ubuntu bash root@9770be5acbab:/#
iptables
command, and you will find a Docker chain rule added:#root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (0 references) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 172.17.0.3 tcp dpt:22
sshclient
:root@ubuntu:~# docker run -i -t --name sshclient --link sshserver:sshserver ubuntu bash root@979d46c5c6a5:/#
root@ubuntu:~# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (0 references) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 172.17.0.3 tcp dpt:22 ACCEPT tcp -- 172.17.0.4 172.17.0.3 tcp dpt:22 ACCEPT tcp -- 172.17.0.3 172.17.0.4 tcp spt:22 root@ubuntu:~#
The following image explains communication between the containers using the --link
flag:
docker inspect
command:root@ubuntu:~# docker inspect -f "{{ .HostConfig.Links }}" sshclient [/sshserver:/sshclient/sshserver]
Now you can successfully ssh into sshserver with its IP.
#ssh [email protected] –p 22
Using the --link
parameter, Docker creates a secure channel between the containers that doesn't need to expose any ports externally on the containers.