Docker networks
Docker has kept its popularity for quite a few years now (without surprise). Its success is based on many things like scalling, microservices and also its network solutions (and many more). In this article I’ll focus solely on docker networks and how they work.
Types of networks – bridge
Bridge is a default network which connects all containers and which has no defined network (–network option in CLI or networks in docker-compose).
Let’s take a look at this simple docker-compose:
version: '3.9'
services:
mongo:
image: mongo
networks:
basicBridge:
aliases:
- mongoBridge
ports:
- "27017:27017"
networks:
basicBridge:
driver: bridge
With this file I will create a container with mongoDB inside, that will expose port 27017 and will use bridge network (or, to be more specific – a virtual network) created with this file. If we inspect our docker networks, we will see:
Ok, the network is created, but how did this affect our iptables?
user@user-VirtualBox:~/docker$ sudo iptables -S
-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o br-f2d613c3f4ae -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-f2d613c3f4ae -j DOCKER
-A FORWARD -i br-f2d613c3f4ae ! -o br-f2d613c3f4ae -j ACCEPT
-A FORWARD -i br-f2d613c3f4ae -o br-f2d613c3f4ae -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.20.0.2/32 ! -i br-f2d613c3f4ae -o br-f2d613c3f4ae -p tcp -m tcp --dport 27017 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-f2d613c3f4ae ! -o br-f2d613c3f4ae -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o br-f2d613c3f4ae -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
And if we grep these full iptable rules (I will return to this full iptables rules later)
-A FORWARD -o br-f2d613c3f4ae -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-f2d613c3f4ae -j DOCKER
-A FORWARD -i br-f2d613c3f4ae ! -o br-f2d613c3f4ae -j ACCEPT
-A FORWARD -i br-f2d613c3f4ae -o br-f2d613c3f4ae -j ACCEPT
-A DOCKER -d 172.20.0.2/32 ! -i br-f2d613c3f4ae -o br-f2d613c3f4ae -p tcp -m tcp --dport 27017 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-f2d613c3f4ae ! -o br-f2d613c3f4ae -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o br-f2d613c3f4ae -j DROP
We can see there our port 27017
-A DOCKER -d 172.20.0.2/32 ! -i br-f2d613c3f4ae -o br-f2d613c3f4ae -p tcp -m tcp --dport 27017 -j ACCEPT
exposed as well as easy movement of bytes between every possible container within this network. It we further inspect this network
user@user-VirtualBox:~/docker$ docker network inspect docker_basicBridge
[
{
"Name": "docker_basicBridge",
"Id": "f2d613c3f4aec2fc21bfe873afb99e5be8169a160f6e4d0287a90935db78066d",
"Created": "2021-02-11T14:20:43.946508597+01:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"5fe027febae2925af2aa1420ed0a8ada62ca3fdb4fe626fe0efc63692be7129f": {
"Name": "docker_mongo_1",
"EndpointID": "06105ac37fe92c35b7ff8fba1159b1adb899c35808fb0566455aca8a42ce8134",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "basicBridge",
"com.docker.compose.project": "docker",
"com.docker.compose.version": "1.25.5"
}
}
]
We notice things
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
and
"Containers": {
"5fe027febae2925af2aa1420ed0a8ada62ca3fdb4fe626fe0efc63692be7129f": {
"Name": "docker_mongo_1",
"EndpointID": "06105ac37fe92c35b7ff8fba1159b1adb899c35808fb0566455aca8a42ce8134",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
}
}
We see ip and subnet that is generated by the bridge driver. The 172.20.0.1 is a default value, although it can be changed.
It is important to remember that bridge is a network that pretty much by default limits itself only to localhost.
Types of network – none
In a full iptables -S list you could only see rules for a standard docker0 (default bridge) and our custom bridge interfaces. None of the lists (as can you suspect) literally cuts the container off the network by not binding it with any docker network. That also means none of ports has been exposed and that ther is no connection from outside the world. For example, if we run simple container
user@user-VirtualBox:~/docker$ docker run -d --network none -p 21017:21017 mongo
and list it
user@user-VirtualBox:~/docker$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
640095c2388e mongo "docker-entrypoint.s…" 3 seconds ago Up 2 seconds intelligent_montalcini
Types of network – host and macvlan
The host network basically uses your host network rules for containers. As you can also suspect, port exposition will no work since apps inside our containers already use our network, not the default virtual one.
Macvlan is just a host network which will let you define the subnet and the gateway for your containers as well as physical network interface (as I wrote in the bridge section, our default docker networks are virtual networks).
Summary
There is also an overlay network, but I will skip it in this article. The reason is that I would have to go through swarm which is big and complex enough for a separate paper. But is that all? As you may notice, I have used the word 'driver’ few times. That’s because docker network uses 3-rd company solutions and this means that there are many more possibilities. So if you ever need something different, maybe there is already a solution for your needs. Or maybe write your own one. Anyway, I hope I have answered for at least a few questions that you had in mind about docker networks.
Peace!