Docker Networking ( Bridge Network Overview )


Docker containers need a networking layer to be able to communicate with each other, with the host machine, or to the outside world. 


Docker Network Types

Docker has different network drivers for different use cases. The most common network types being:  bridgehost, and  none.


Default network

When Docker is installed, by default a bridge network is created. 

gaurav@learning-ocean:~$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
6c51373f78ac   bridge    bridge    local
3a33f83c3663   host      host      local
e4ebd601732c   none      null      local
gaurav@learning-ocean:~$

Let's inspect this network-

gaurav@learning-ocean:~$ docker network inspect bridge

output:

gaurav@learning-ocean:~$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "6c51373f78ac20709cd6d6209d6f3c26fcb589e9515e125d9cfce1cccd00d3c8",
        "Created": "2021-08-03T12:06:45.128077928Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
gaurav@learning-ocean:~$

Here you can see no containers are assigned to it as there are no containers present.


Now, let’s create a new container from nginx image-

gaurav@learning-ocean:~$ docker container ls
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
gaurav@learning-ocean:~$ docker container run -itd nginx
e8d75d357800e3f9dde4ba2af3548084311d9957f8daa16d90f8055fcabb9255
gaurav@learning-ocean:~$ docker container rm e8 -f
e8
gaurav@learning-ocean:~$

Inspecting the bridge network again and output is-


# few lines removed from output
  "Containers": {
            "fe84061dd9623d11b640b8b437aa8145e4303d404a300a34932b8ac552cca7ac": {
                "Name": "boring_lovelace",
                "EndpointID": "e820a04ce51a5c8d835adbc341ef6cbfcd198f8eeecaaa371cec212a012c3c72",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
# few lines removed from output


Now the container is not empty and is being assigned with the new container that we just created. This shows that whenever we create a new container, it will be assigned a bridge network.


Bridge network deep dive


Let’s now create a new container with an ubuntu image-


gaurav@learning-ocean:~$ docker container run -it ubuntu:14.04 bash


And if we ping 8.8.8.8 from here, it will start sending and receiving the packets as the container has internet access. 

[email protected]:/# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=17.0 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=19.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=114 time=17.7 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=114 time=16.3 ms
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 16.367/17.589/19.169/1.034 ms
[email protected]:/#


How do these packets flow?


Consider the diagram below-

docker-docker-networking


Whenever we create a container, the bridge network - docker0 gets created.


To check the details about the virtual bridge, use ifconfig command on docker host-

gaurav@learning-ocean:~$ ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:d6ff:fef2:507  prefixlen 64  scopeid 0x20<link>
        ether 02:42:d6:f2:05:07  txqueuelen 0  (Ethernet)
        RX packets 6  bytes 392 (392.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 11  bytes 922 (922.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.11  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::a00:27ff:fee8:5e4  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:e8:05:e4  txqueuelen 1000  (Ethernet)
        RX packets 23158  bytes 31166066 (31.1 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12167  bytes 1032096 (1.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 190  bytes 16549 (16.5 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 190  bytes 16549 (16.5 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


veth597ef41: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::60f8:1bff:fefa:6e2d  prefixlen 64  scopeid 0x20<link>
        ether 62:f8:1b:fa:6e:2d  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 18  bytes 1424 (1.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


gaurav@learning-ocean:~$



docker0:  Docker Interface

enp0s3: NIC interface

Lo: loopback

veth597ef41: A vertical ethernet pair is created, one end is attached to the container and  the other to the virtual bridge network


When we pinged from the container the packet flow is like-

docker-docker-networking


If we try to access NGINX container from browser we won't be able to access because there is no port that can listen the request-

To assign a port to the container, use below docker command with -p parameter-

gaurav@learning-ocean:~$ docker container run -Pd nginx
a715131c3a72d759614617949c8625d1f59d51c271d93f50e9006172a37f1fc5

Listing the containers -

gaurav@learning-ocean:~$ docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                   NAMES
fe84061dd962   nginx     "/docker-entrypoint.…"   18 minutes ago   Up 18 minutes   80/tcp                 boring_lovelace
a715131c3a72   nginx     "/docker-entrypoint.…"   2 seconds ago    Up 1 second    0.0.0.0:32771->80/tcp   elegant_wilson
gaurav@learning-ocean:~$


Docker container has been assign the port on eth0 of docker host which can be accessed over the internet.

docker-docker-networking


Any traffic coming to this port will be going via the bridge network to port 80 of the containers.

docker-docker-networking