NETWORKING WITH DOCKER

This hands-on guide will help you understand how networking works with Docker and containers in linux. Learn in these simple steps how to customise and create user defined network.
When you install Docker, it creates three networks automatically. You can list *these networks using the docker network ls
command:
root@ubuntu:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
f0a2eabc9004 bridge bridge local
84b903e031be host host local
c82ab14d5177 none null local
root@ubuntu:~#
These three networks are built into Docker. When you run a container, you can use the --network
flag to specify which networks your container should connect to.
- The
bridge
network represents thedocker0
network present in all Docker installations. Unless you specify otherwise with thedocker container run --network=<NETWORK>
option, the Docker daemon connects containers to this network by default. You can see this bridge as part of a host’s network stack by using theifconfig
command on the host.
root@ubuntu:~# ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:9f:33:c6:42
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:9fff:fe33:c642/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:23605 errors:0 dropped:0 overruns:0 frame:0
TX packets:54913 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:6884705 (6.8 MB) TX bytes:25698564 (25.6 MB)
- The
none
network adds a container to a container-specific network stack. That container lacks a network interface. - The
host
network adds a container on the host’s network stack. As far as the network is concerned, there is no isolation between the host machine and the container. For instance, if you run a container that runs a web server on port 80 using host networking, the web server is available on port 80 of the host machine.
The none
and host
networks are not directly configurable in Docker. However, you can configure the default bridge
network, as well as your own user-defined bridge networks.
LIST THE CURRENT DOCKER NETWORKS
root@ubuntu:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
f0a2eabc9004 bridge bridge local
84b903e031be host host local
c82ab14d5177 none null local
CREATE A ALPINE CONTAINER NAMED CONTAINER1 AND INSPECT THE /ETC/RESOLV.CONF AND /ETC/HOSTS FILE. ALSO NOTE THE IP ADDRESS OF THE CONTAINER.
root@ubuntu:~# docker run -itd --name=container1 alpine sh
37985ded1e9c462561d81a953552cb58a3a832f819746e18e01c65554b56fc07
root@ubuntu:~# docker exec container1 cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 10.0.2.3
root@ubuntu:~# docker exec container1 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 37985ded1e9c
root@ubuntu:~# docker inspect container1 |grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
CREATE ANOTHER ISOLATED BRIDGE NETWORK NAMED BRIDGE2
root@ubuntu:~# docker network create --driver bridge --subnet 192.168.111.1/24 bridge2
5340acb01851b00a2143383056d67e625ee77b67dca02242a50bea168090587d
root@ubuntu:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
f0a2eabc9004 bridge bridge local
5340acb01851 bridge2 bridge local
84b903e031be host host local
c82ab14d5177 none null local
root@ubuntu:~# ifconfig
br-5340acb01851 Link encap:Ethernet HWaddr 02:42:fb:50:db:04
inet addr:192.168.111.1 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST MULTICAST MTU:1500 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)
docker0 Link encap:Ethernet HWaddr 02:42:9f:33:c6:42
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:9fff:fe33:c642/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:23608 errors:0 dropped:0 overruns:0 frame:0
TX packets:54919 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:6884901 (6.8 MB) TX bytes:25698928 (25.6 MB)
CREATE ANOTHER ALPINE CONTAINER NAMED CONTAINER2 ATTACHED TO BRIDGE2 NETWORK AND INSPECT THE /ETC/RESOLV.CONF AND /ETC/HOSTS FILE. ALSO NOTE THE IP ADDRESS OF THE CONTAINER.
root@ubuntu:~# docker run -itd --name=container2 --net=bridge2 alpine sh
f084cd26d2c0967a2d839c7467312063752e8715b27b91416b8c21e5ecf02340
root@ubuntu:~# docker exec container2 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.111.2 f084cd26d2c0
root@ubuntu:~# docker exec container2 cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
root@ubuntu:~# docker inspect container2 |grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "",
"IPAddress": "192.168.111.2",
root@ubuntu:~#
TRY ACCESSING CONTAINER1 FROM CONTAINER2
root@ubuntu:~# docker exec -it container2 sh
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
^C
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
CREATE THIRD ALPINE CONTAINER CONNECTED TO BOTH BRIDGE NETWORKS. ALSO INSPECT THE /ETC/RESOLV.CONF AND /ETC/HOSTS FILE. ALSO NOTE THE IP ADDRESS OF THE CONTAINER.
root@ubuntu:~# docker run -itd --name=container3 alpine sh
1726892f1b42d308321cc07c0e90c12183b00f99225dc539a5bed0ad801ca649
root@ubuntu:~# docker network connect bridge2 container3
root@ubuntu:~# docker exec -it container3 sh
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 1726892f1b42
192.168.111.3 1726892f1b42
/ # cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:03
inet addr:172.17.0.3 Bcast:0.0.0.0 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 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:648 (648.0 B) TX bytes:0 (0.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:C0:A8:6F:03
inet addr:192.168.111.3 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 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:648 (648.0 B) TX bytes:0 (0.0 B)
TRY ACCESSING CONTAINER1 AND CONTAINER2 FROM CONTAINER3 USING IP ADDRESS AND NAME. ALSO CHECK CONNECTIVITY TO EXTERNAL NETWORK.
/ # ping -c3 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.138 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.120 ms
64 bytes from 172.17.0.2: seq=2 ttl=64 time=0.116 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.116/0.124/0.138 ms
/ # ping -c3 192.168.111.2
PING 192.168.111.2 (192.168.111.2): 56 data bytes
64 bytes from 192.168.111.2: seq=0 ttl=64 time=0.126 ms
64 bytes from 192.168.111.2: seq=1 ttl=64 time=0.130 ms
64 bytes from 192.168.111.2: seq=2 ttl=64 time=0.134 ms
--- 192.168.111.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.126/0.130/0.134 ms
/ # ping -c3 container1
ping: bad address 'container1'
/ # ping -c3 container2
PING container2 (192.168.111.2): 56 data bytes
64 bytes from 192.168.111.2: seq=0 ttl=64 time=0.151 ms
64 bytes from 192.168.111.2: seq=1 ttl=64 time=0.118 ms
64 bytes from 192.168.111.2: seq=2 ttl=64 time=0.130 ms
--- container2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.118/0.133/0.151 ms
/ # ping -c3 google.com
PING google.com (216.58.199.174): 56 data bytes
64 bytes from 216.58.199.174: seq=0 ttl=61 time=22.968 ms
64 bytes from 216.58.199.174: seq=1 ttl=61 time=61.807 ms
64 bytes from 216.58.199.174: seq=2 ttl=61 time=35.257 ms
--- google.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 22.968/40.010/61.807 ms
Note that container1 belongs to the default bridge network and so is not accessible using name where as container2 belongs to the user-defined-network running a embedded DNS server which resolves the container names on the same network.
CREATE ANOTHER NETWORK NAMED BRIDGE3 AND RESTRICT EXTERNAL ACCESS TO THE NETWORK BY USING --INTERNAL OPTION
root@ubuntu:~# docker network create --internal bridge3
84322cf4cfb6f70d553e23b2753b48d24c28d7eaba2016a6134da1b4691792aa
root@ubuntu:~# docker run -itd --name=container4 --net=bridge3 alpine sh
caa817054e0cb86dddf312d33b1e2357f7af728f7b60527b9a4b4bfaf4e1b511
root@ubuntu:~# docker exec -it container4 sh
/ # ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
^C
--- 8.8.8.8 ping statistics ---
5 packets transmitted, 0 packets received, 100% packet loss
/ # exit
ALSO CHECK THE IPTABLES RULES. MASQUERADING IS DISABLED ON THE INTERNAL NETWORK
root@ubuntu:~# iptables -t nat -L -n |grep MASQUERADE
MASQUERADE all -- 192.168.111.0/24 0.0.0.0/0
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
root@ubuntu:~#
Enjoy :)