Learn Docker Network
Tags: docker, network, container
Published: 2020-04-29 16:48:54

What is called network in docker is an abstraction created to make it simple to manage the communication among containers and external nodes. There's nothing much in common with the IP network (as example 10.0.0.1/24...)

#Docker's default networks
Docker gives to you three default networks with specific configurations, to see those just use the command:
```
$ docker network ls
```
Those networks are: bridge; none; host.
Talking first about the bridge:
##Bridge
Each container started in Docker is associated to a specific network, without that association, the default will be bridge, this network received an address that is avaliable within network IP 172.17.0.0/16 (CIDR) and all containers into this network may connect through TCP/IP. But wait, you must know the IP of the container that you wanna connect to, and this is difficult because those IPs are automatically given, so there's this thing called "--link", you gonna use it when you want to specific a DNS to a container that you are starting, a specific container, so the container A can connect to container B.
To explain this brief case, lets create a container A that wanna connect to B, first creating B:
```
$ docker container run -d --name B [image_name]
```
And now creating A:
```
$ docker container run -d --name A --link B [image_name]
```
Now you can ping A to B simply using this command:
```
$ docker container exec -it A ping B
```
But now unlearn it (really), it's an old way (legacy), so now the Docker treats it through DNS resolution automatically. An important thing to mention here is that all containers within this network will have access to all internet resources that the host has, and you can expose ports of the container to the outside world too.

##None
This network is simple to explain, its purpose is to only isolate the container to the outside world and for the host. This network simply says that there's no network inside the container and its purpose of use is for containers that don't need it, containers that will use only mapped volumes to make backups, for example.

##Host
This kind of network simply expose all host's interfaces to the container. In certain way this host is faster cause there isn't a bridge in the way of the packets, but the bridge still important to secure and manage the network.

##User network
In Docker the user can create your own network, that created network is associated to a thing named "network driver", each network created by the user must be associated to a determined driver, and in case where the user don't create a driver, he must choose among the different drivers provided by docker.
###Bridge (Driver)
Yes, there's a driver called "bridge" too, and the default network created by the user is similar to bridge network, but pay attention:
> Created network have all features present in bridge network, __plus__ it makes unnecessary to provide a "--link" to connect to other container, it uses an internal DNS resolution from Docker to connect its containers, it's specially an interesting thing when we are using the docker-compose to create more than one container that establish communication.
But now, let see how we can create a new network named "my_network":
```
$ docker network create --driver bridge my_network
```
And we can see that as a result of the command:
```
$ docker network list
```
We get:
```
NETWORK ID          NAME                DRIVER              SCOPE
3cf03b36d2fe        bridge              bridge              local
42517bb97000        host                host                local
a0ad7b22784f        my_network          bridge              local
1f98998e1711        none                null                local
```
Now to a better understand of what we learnt until now, let's create a container named "container_a" and another named "container_b" and connect both to our network "my_network" and ping "container_b" from "container_a", first creating "container_b":
```
docker container run -d --net my_network --name container_b alpine tail -f /dev/null
```
And then create container_a and tell him to ping container_b:
```
docker container run -it --net my_network --name container_a alpine ping container_b
```
And that is our output:
```
PING container_b (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.080 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.114 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.084 ms
64 bytes from 172.18.0.2: seq=3 ttl=64 time=0.068 ms
64 bytes from 172.18.0.2: seq=4 ttl=64 time=0.069 ms
64 bytes from 172.18.0.2: seq=5 ttl=64 time=0.197 ms
64 bytes from 172.18.0.2: seq=6 ttl=64 time=0.209 ms
64 bytes from 172.18.0.2: seq=7 ttl=64 time=0.090 ms
^C
--- container_b ping statistics ---
8 packets transmitted, 8 packets received, 0% packet loss
round-trip min/avg/max = 0.068/0.113/0.209 ms
```
As we saw the Docker automatically created the DNS resolve and gave the IP 172.18.0.2, so it becomes transparent as we just need to refer to container_b by its name.

Now a curious thing is that we can see which containers are within our new created network, to do so run the command:
```
docker network inspect my_network
```
And you'll get:
```
[
    {
        "Name": "my_network",
        "Id": "a0ad7b22784f70f3cd21edc0868fb84be5cf11ebd516dcb760f096f1a683607a",
        "Created": "2020-04-29T14:57:15.2716747Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "5aafff23f51d44836b2de86b7ee7686d8187fbe57a450fa095139b46f9fe7081": {
                "Name": "container_b",
                "EndpointID": "f724a6b2adb8dbd3e04716963058f1959e2684abe2b6dbb17e05cad24e89b9a6",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "5b2d2708c8d4392c4f1e2bda3009e9498c64c4cd12cecafbbcafc2f6593453d1": {
                "Name": "container_a",
                "EndpointID": "7f59020df5559e77ac8bff04204ede21328a3c55d82695f4aa7f8a311c9b2a85",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
```
###Overlay
I'll not go deep in this topic here, but just to know the purpose of Overlay driver is to establish connection among hosts docker, it has a bit complex configuration but i full recommend you to search about if you gonna need to communicate containers among different hosts.

Ok, we finished for now, I hope you enjoy it!

This post is part of a series about docker, to see more please follow the tag series: docker-by-tiagomac, keep learning and practicing.