Docker network + macvlan

Seguimos con los posts de docker y ahora toca uno sobre el tema de networking.

La necesidad básica es la de publicar a Internet un servidor web con nginx. En lugar de definir la IP pública al servidor docker nos interesa ponerla dentro del contenedor de nginx y luego que él sea el que tenga acceso al resto de máquinas.

El servidor de docker con el que estoy trabajando es una máquina física con debian con una IP de guifi (10.90.234.170) y en el datacenter donde está en la VLAN 138 está el rango de IP públicas (5.10.205.128/27).

Crear la network

Docker por defecto trae 3 networks, por defecto cuando creamos un contenedor nuevo asigna la red bridge (driver bridge) 172.17.0.0/16

root@wezen02:~# docker network ls
NETWORK ID          NAME                           DRIVER              SCOPE
f9e3dcfa1e06        bridge                         bridge              local
262f24ac9f10        host                           host                local
c4572142389a        none                           null                local

Para crear una nueva red y vincularla a la vlan correspondiente usaremos lo siguiente:

# docker network create -d macvlan -o parent=eno1.138 public

Cuando creamos una nueva red docker le asigna un rango por defecto correlativo al último rango creado, por ejemplo 172.18.0.0/16 pero nos interesa que cuando asignemos ésta network a un contenedor le asigne una IP de nuestro rango público.

# docker network rm public
# docker network create -d macvlan -o parent=eno1.138 public --subnet=5.10.205.128/27 --gateway=5.10.205.129 --ip-range 5.10.205.152/29

Con –subnet indicamos la red en la que trabaja la network, –gateway la puerta de enlace de nuestro router e –ip-range el rango que asignará automáticamente a los contenedores cuando los creemos sin especificar ninguna IP.

Asignar la network a un contenedor

Para asignar una network a un contenedor lo podremos hacer de varias formas.

La primera es crear un contenedor con la red por defecto bridge y luego conectarle la red

# docker run -dti --name nginx -p 80:80 --restart=always nginx
# docker network connect public nginx

O la otra es asignarle la red al crear el contenedor

# docker run -dti --name nginx -p 80:80 --restart=always --network=public nginx
d94856846939bc657cab982b972fe943532eed3803beb40ef35e3241ff2c9d28

# docker exec -ti nginx /bin/bash
root@d94856846939:/# ifconfig     
eth0: flags=4163  mtu 1500
        inet 5.10.205.152  netmask 255.255.255.224  broadcast 5.10.205.159
        ether 02:42:05:0a:cd:98  txqueuelen 0  (Ethernet)
        RX packets 6639  bytes 9096369 (8.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4618  bytes 370924 (362.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 6  bytes 542 (542.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6  bytes 542 (542.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@d94856846939:/# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         5.10.205.129    0.0.0.0         UG    0      0        0 eth0
5.10.205.128    0.0.0.0         255.255.255.224 U     0      0        0 eth0

Tendremos la opción también de definir una IP de forma estática

# docker run -dti --name nginx -p 80:80 --restart=always --network=public --ip 5.10.205.153 nginx
3a3d06e249854dcbb812b3ec755b067eb9ab8a424f2d4dd9f4e1b17dd5c6ed69

# docker exec -ti nginx /bin/bash
root@3a3d06e24985:/# ifconfig
eth0: flags=4163  mtu 1500
        inet 5.10.205.153  netmask 255.255.255.224  broadcast 5.10.205.159
        ether 02:42:05:0a:cd:98  txqueuelen 0  (Ethernet)
        RX packets 5907  bytes 9049480 (8.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4595  bytes 370493 (361.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 6  bytes 542 (542.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6  bytes 542 (542.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@3a3d06e24985:/# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         5.10.205.129    0.0.0.0         UG    0      0        0 eth0
5.10.205.128    0.0.0.0         255.255.255.224 U     0      0        0 eth0

Otros comandos que nos pueden interesar para ésta parte son:

# docker network inspect public

# docker inspect nginx

# docker inspect nginx |grep 'IPAddress'
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "5.10.205.153",

# docker inspect nginx |grep 'Gateway'
            "Gateway": "",
            "IPv6Gateway": "",
                    "Gateway": "5.10.205.129",
                    "IPv6Gateway": "",

# docker inspect nginx |grep 'Port'
            "PortBindings": {
                        "HostPort": "80"
            "PublishAllPorts": false,
            "ExposedPorts": {
            "Ports": {},

Comentar que gracias al funcionamiento de docker, se podrá resolver desde éste contenedor los otros contenedores por su nombre de contenedor, así que en el caso de éste nginx nos referiremos a los otros contenedores por su nombre de contenedor y no su IP.

Otros links de interés para seguir investigando sobre éste tema:

docker documentation: docker network create
docker documentation: docker network connect
docker documentation: Use macvlan networks
docker documentation: Disable networking for a container
oddbit: USING DOCKER MACVLAN NETWORKS
dockertips: Redes en Docker

Deixa un comentari

L'adreça electrònica no es publicarà.

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.