Como ya hemos comentado Docker crea una interfaz de red propia con el nombre de docker0. Esta red tiene un rango típico: 174.17.0.1/24
. Las primeras versiones de Docker presentaban problemas de seguridad o más bien de confiabilidad ya que cualquier contenedor de un host podía tener acceso a cualquier contenedor del mismo.
La versiones más modernas permiten crear distintas subredes y aislar perfectamente grupos de contenedores para no permitir accesos no autorizados.
Tipos de red.
Para mostrar los tipos de red disponibles por defecto en Docker, sólo hay que ejecutar:
>_ docker network ls
NETWORK ID NAME DRIVER
eb2291dd0b63 bridge bridge
b9e68dd550d4 host host
ccc5be97afaf none null
Estas los las distintas redes que tenemos configuradas por defecto en nuestro host.
- host representa la red del propio equipo y haría referencia a
eth0
- bridge representa la red
docker0
y a ella se contectan todos los contendeores por defecto. - none significa que el contenedor no se incluye en ninguna red y si verificaramos esto con el comando
ifconfig
dentro del contenedor veríamos que solo tiene la interfaz de loopbacklo
.
Bridge en detalle.
Podemos ver en detalle que parametros tiene cada red usando docker network inspect <red>
.
>_ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "eb2291dd0b63bce452f37518c1ba4d248568301f9862f58fdc6c6c403779879c",
"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,
"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": {}
}
]
Podemos comprobar como por defecto crear una subred (clase B) que iría desde la 172.17.0.1 a la 172.17.255.254. Pudiendo albergar 65534 contenedores.
Por otro lado vemos como el campo Containers
está vacío ya que inicialmente no tenemos ningún contenedor en funcionamiento. Tras crear 2 contenedores veremos lo siguiente:
>_ docker run -itd --name=container1 busybox
d7555b818efc201e4715d1e17bde340eaabf788450d9f83682365efad13a2205
>_ docker run -itd --name=container2 busybox
5450fab33b65f1d4b1446e0464ea6e9084399d5ba71e1b74224a4c1759f96b7b
>_ docker network inspect bridge
[
...
"Internal": false,
"Containers": {
"5450fab33b65f1d4b1446e0464ea6e9084399d5ba71e1b74224a4c1759f96b7b": {
"Name": "container2",
"EndpointID": "c42d1a88508472e2c12920141216404233abc3fd14c1fb8fb5982fc1aecb863c",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"d7555b818efc201e4715d1e17bde340eaabf788450d9f83682365efad13a2205": {
"Name": "container1",
"EndpointID": "52e12690fdf6a6f1f20e95969c7bb7e9339f00e8421b77e2cb7bf4d2ed04d83f",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"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": {}
}
]
Ahora vemos como tenemos dos contenedores que pertenecen a la red 172.17.0.1/16 cualquiera de los dos puede ver al otro. Incluso si siguiésemos creando más contenedores estos se verían todos con todos.
Entonces, ¿cómo podemos aislar en subredes?
Redes definidas por nosotros.
Para poder aislar contenedores es necesario definir una red para esos contenedores que sea distinta de la red bridge por defecto. Para ello usamos:
>_ docker network create --driver bridge aislada
>_ docker network ls
NETWORK ID NAME DRIVER
646b570ec240 aislada bridge
eb2291dd0b63 bridge bridge
b9e68dd550d4 host host
ccc5be97afaf none null
Podemos ver que tenemos una nueva red que vamos a usar para aislar un tercer contenedor. Lo único que tendremos que hacer es definirlo a la hora de crear el contenedor.
>_ docker run --net=aislada -itd --name=container3 busybox
>_ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fe5aaddb049 busybox "sh" 16 seconds ago Up 14 seconds container3
5450fab33b65 busybox "sh" 9 minutes ago Up 9 minutes container2
d7555b818efc busybox "sh" 9 minutes ago Up 9 minutes container1
Como vemos hay 3 contenedores, dos en la red por defecto y uno en la nueva red.
Podemos comprobar como desde el contenedor 2 no podemos hacer ping al 3:
>_ docker attach container1
#_ ping -w3 172.18.0.2
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
Esta forma de aislar contenedores nos puede ser útil para pequeñas redes de contenedores todos dentro de un único host. Pero, ¿qué pasa cuando queremos tener más contenedores y nuestro host se queda pequeño?
Necesitamos añadir más hosts y crear una red superpuesta o lo que se llama overlay network.
Redes suprahost o superpuestas
Como ya hemos hablado la red superpuesta sirve para unir varios host de una manera segura utilizando VXLAN. Esta librería permite hacer esto, incluso permite desarrollar nuestros propios drivers.
Para crear una red overlay es imprescindible disponer de un servicio de almacenamiento key-value como Consul , Etcd , o ZooKeeper .
Este servicio se instala en uno de los nodos mientras que en el resto se instala el servicio de Docker.
Estos son los puertos necesarios para usar el servicio de key-value.
Protocolo | Puerto | Descripción |
---|---|---|
udp | 4789 | Nivel de datos (VXLAN) |
tcp/udp | 7946 | Nivel de control |
Desde el punto de vista de cada nodo, es necesario configurar el daemon de Docker para que use la red superpuesta. Los parámetros de configuración son los siguientes:
- –cluster-store=PROVIDER://URL especifica la dirección del servicio key-value
- –cluster-advertise=HOST_IP|HOST_IFACE:PORT Ip o intefaz del host dentro del cluster
- –cluster-store-opt=KEY-VALUE OPTIONS diversas opciones como el certificado TLS o los tiempos de búsqueda de nodos.
Para crear la red overlay usamos:
>_ docker network create --driver overlay my-multi-host-network
Y ahora en cada nodo cuando queramos levantar un contenedor tendremos que usar la red definida como overlay.
>_ docker run -itd --net=my-multi-host-network busybox
Para desarrollo de aplicaciones, testing o integración continua nos servirá perfectamente con la redes que vienen creadas por defecto. Sin embargo si queremos definir más de un servicio en un host o tener un enjambre de host para tener un scalamiento horizontal necesitaremos definir este tipo de redes y conviene conocer estas opciones.
En el siguiente post propondremos un ejemplo de desplegar una aplicación multi-host ya que en este se ha tocado el tema un poco por encima y sin un ejemplo practico.
Por otro lado en la página de Docker puedes encontrar más información respecto al uso de las redes docker
Comentarios recientes