En esta lección daremos un salto cualitativo respecto a lo que vimos en el módulo anterior sobre redes básicas. Ahora analizaremos en profundidad los distintos drivers de red, entenderemos por qué las redes definidas por el usuario son superiores a la red bridge por defecto, exploraremos la resolución DNS interna entre contenedores, distinguiremos claramente entre publicar y exponer puertos, y aprenderemos a inspeccionar y resolver problemas de red. Dominar estos conceptos es esencial para construir arquitecturas de microservicios robustas, seguras y mantenibles.
Los Drivers de Red en Detalle
Docker utiliza un sistema de drivers (controladores) para implementar los distintos tipos de red. Cada driver responde a un caso de uso concreto. Conocer sus diferencias te permite elegir la opción correcta en cada situación.
| Driver | Alcance | Caso de uso principal | Aislamiento | DNS interno |
|---|---|---|---|---|
| bridge | Un solo host | Aplicaciones multi-contenedor en una sola máquina | Alto | Sí (en redes definidas por el usuario) |
| host | Un solo host | Máximo rendimiento de red, sin capa de NAT | Ninguno | No aplica |
| overlay | Múltiples hosts | Servicios distribuidos en Swarm o clústeres | Alto | Sí |
| macvlan | Un solo host | El contenedor aparece como un dispositivo físico en la LAN | Medio | Limitado |
| none | Un solo host | Contenedores totalmente aislados sin red | Máximo | No |
Driver bridge
Es el driver predeterminado. Crea una red interna privada en el host mediante un puente virtual de Linux (docker0 para la red por defecto). Los contenedores conectados reciben una IP de un rango privado y se comunican entre sí a través de ese puente.
docker network create: comando para crear una red.--driver bridge: especifica el driver. Aunque bridge es el valor por defecto, indicarlo de forma explícita mejora la legibilidad.mi_red_app: nombre de la red.
Driver host
Elimina el aislamiento de red entre el contenedor y el host: el contenedor utiliza directamente la pila de red del anfitrión.
--network host: el contenedor comparte la red del host. Si Nginx escucha en el puerto 80, lo hará directamente sobre el puerto 80 del host, sin necesidad de-p.
Ventaja: rendimiento máximo (no hay NAT ni traducción de puertos). Desventaja: pierdes el aislamiento y dos contenedores no pueden usar el mismo puerto.
Driver overlay
Permite que contenedores ubicados en hosts diferentes se comuniquen como si estuvieran en la misma red local. Es la base de Docker Swarm.
# Requiere un nodo en modo Swarm
docker swarm init
docker network create --driver overlay --attachable mi_red_overlaydocker swarm init: inicializa el modo Swarm en el nodo actual.--attachable: permite que contenedores independientes (no solo servicios de Swarm) se conecten a la red.
Driver macvlan
Asigna a cada contenedor una dirección MAC propia, haciéndolo visible en la red física como si fuera un equipo más.
docker network create -d macvlan \
--subnet=192.168.10.0/24 \
--gateway=192.168.10.1 \
-o parent=eth0 \
mi_red_macvlan--subnety--gateway: definen el rango de IP y la puerta de enlace de la red física.-o parent=eth0: indica la interfaz física del host a la que se asocia. Sustituyeeth0por el nombre real de tu interfaz.
Driver none
Desactiva por completo la red del contenedor. Solo tendrá la interfaz de loopback (lo). Útil para procesos por lotes que no requieren conectividad.
Redes Definidas por el Usuario vs. la Red Bridge por Defecto
Cuando ejecutas un contenedor sin especificar red, este se conecta a la red bridge por defecto llamada bridge. Sin embargo, esta red tiene limitaciones importantes y no se recomienda para producción.
| Característica | Bridge por defecto | Bridge definida por el usuario |
|---|---|---|
| Resolución DNS por nombre | No (solo por IP) | Sí (por nombre de contenedor) |
| Aislamiento entre aplicaciones | Todos comparten la red | Cada red está aislada |
| Conexión/desconexión en caliente | Limitada | Total |
| Configuración personalizada (subred, gateway) | No | Sí |
La diferencia más importante es la resolución DNS automática. En una red definida por el usuario, los contenedores pueden encontrarse por su nombre; en la red bridge por defecto, solo por IP, lo cual es frágil porque las IP cambian.
# Crear la red y conectar dos contenedores
docker network create tienda_red
docker run -d --name api --network tienda_red node:18-alpine
docker run -d --name frontend --network tienda_red nginxAhora el contenedor frontend puede contactar con api simplemente usando el nombre api como nombre de host.
Resolución DNS Interna entre Contenedores
Docker incorpora un servidor DNS embebido (accesible en la IP 127.0.0.11 dentro de cada contenedor) que resuelve automáticamente los nombres de los contenedores conectados a la misma red definida por el usuario.
- Docker traduce el nombre
apia la IP interna del contenedor correspondiente. - Esto funciona sin que tengas que editar ficheros como
/etc/hostsmanualmente.
También puedes asignar alias de red adicionales:
--network-alias servicio-pedidos: además deapi, el contenedor también responderá al nombreservicio-pedidosdentro de la red.
Publicación de Puertos: -p vs. --expose
Es habitual confundir estas dos opciones, pero hacen cosas muy distintas.
| Opción | Qué hace | ¿Accesible desde el host? |
|---|---|---|
-p |
Publica un puerto del contenedor en el host (crea regla de NAT) | Sí |
--expose |
Documenta/declara que el contenedor escucha en un puerto | No (solo a otros contenedores) |
Publicar puertos con -p
8080:80: mapea el puerto8080del host al puerto80del contenedor.- Desde tu navegador podrás acceder a
http://localhost:8080.
Puedes limitar la exposición a una interfaz concreta del host por seguridad:
127.0.0.1:8080:80: el puerto solo será accesible desde el propio host (localhost), no desde la red externa.
Declarar puertos con --expose
--expose 3000: indica que el contenedor escucha en el puerto3000. Otros contenedores de la misma red podrán acceder aapi:3000, pero el puerto no se publica en el host.
Comunicación entre Contenedores y Aislamiento de Red
Cada red definida por el usuario es un dominio de aislamiento. Dos contenedores en redes distintas no se ven entre sí, salvo que conectes uno de ellos a ambas redes.
# Crear dos redes aisladas
docker network create red_frontend
docker network create red_backend
# La base de datos solo en la red backend (aislada del exterior)
docker run -d --name db --network red_backend postgres:16
# La API conectada a ambas redes para actuar de puente
docker run -d --name api --network red_backend node:18-alpine
docker network connect red_frontend api
# El frontend solo en la red frontend
docker run -d --name web --network red_frontend nginx- La base de datos
dbqueda aislada: solo laapipuede alcanzarla. docker network connect red_frontend api: conecta el contenedorapitambién a la red frontend, permitiéndole comunicarse conweb.- Este patrón implementa el principio de mínima exposición: la base de datos nunca queda accesible desde la red del frontend.
Inspección y Troubleshooting de Redes
Cuando algo no funciona, estos comandos son tus mejores aliados.
Inspeccionar una red
- Muestra la subred, la puerta de enlace y, lo más útil, la lista de contenedores conectados con sus IP. Ideal para confirmar que un contenedor está realmente en la red que crees.
Ver las redes de un contenedor
-f '{{json ...}}': aplica una plantilla de formato Go para extraer solo la sección de redes en formato JSON.
Diagnóstico desde dentro del contenedor
# Instalar herramientas de red en una imagen Alpine
docker exec -it api sh -c "apk add --no-cache iputils bind-tools"
# Comprobar conectividad
docker exec -it api ping -c 3 db
# Comprobar resolución DNS
docker exec -it api nslookup dbping -c 3 db: envía 3 paquetes adbpara verificar conectividad de capa 3.nslookup db: confirma que el DNS interno resuelve el nombre a una IP.
Limpiar redes sin uso
- Elimina todas las redes que no tengan ningún contenedor conectado. Muy útil para mantener limpio el entorno.
Errores Comunes y Consejos
- Usar la red bridge por defecto en producción: pierdes el DNS por nombre. Crea siempre redes definidas por el usuario.
- Confundir
-pcon--expose: si no puedes acceder desde el navegador, probablemente usaste--exposeen lugar de-p. - Olvidar que los nombres deben estar en la misma red: el DNS interno solo resuelve nombres de contenedores conectados a la misma red definida por el usuario.
- Conflictos de subred: al crear redes con
--subnet, evita rangos que solapen con tu red física para no provocar problemas de enrutamiento. - Asumir que
localhostdentro del contenedor es el host: dentro de un contenedor,localhostse refiere al propio contenedor, no a la máquina anfitriona. - Consejo: nombra tus redes de forma descriptiva (
red_backend,red_pagos) para que la topología sea autoexplicativa.
Ejercicios
Ejercicio 1: Aislamiento de tres capas
Crea una arquitectura de tres capas (web, api, base de datos) donde la base de datos solo sea accesible por la api, y la web solo pueda hablar con la api. Verifica que la web NO puede alcanzar la base de datos.
Ejercicio 2: Resolución DNS y alias
Crea una red definida por el usuario, lanza un contenedor llamado cache con el alias redis-server, y desde otro contenedor comprueba que ambos nombres resuelven correctamente.
Ejercicio 3: Diferencia entre publicar y exponer
Lanza dos contenedores Nginx: uno con -p 8081:80 y otro con --expose 80. Comprueba a cuál puedes acceder desde el navegador del host y razona por qué.
Soluciones
Solución 1
docker network create red_frontend
docker network create red_backend
docker run -d --name db --network red_backend postgres:16
docker run -d --name api --network red_backend node:18-alpine
docker network connect red_frontend api
docker run -d --name web --network red_frontend nginx
# La web NO debe poder resolver ni alcanzar db
docker exec -it web ping -c 2 db # Debe fallar (host desconocido)
# La api SÍ alcanza db
docker exec -it api ping -c 2 db # Debe funcionarLa web no encuentra a db porque ambos están en redes distintas y no comparten dominio DNS.
Solución 2
docker network create red_app
docker run -d --name cache --network red_app --network-alias redis-server redis:7-alpine
docker run -d --name worker --network red_app alpine sleep 3600
docker exec -it worker sh -c "apk add --no-cache bind-tools && nslookup cache && nslookup redis-server"Ambos nombres resuelven a la misma IP del contenedor cache.
Solución 3
Solo http://localhost:8081 responde. El contenedor expuesto no publica ningún puerto en el host; --expose únicamente declara el puerto para la comunicación entre contenedores de la misma red.
Conclusión
En esta lección hemos profundizado en el sistema de redes de Docker: los distintos drivers y cuándo usar cada uno, la superioridad de las redes definidas por el usuario gracias al DNS interno, la diferencia crítica entre publicar (-p) y exponer (--expose) puertos, los patrones de aislamiento entre capas y las herramientas para diagnosticar problemas. Estas técnicas son la base de cualquier arquitectura distribuida segura.
En la siguiente lección, Opciones de Almacenamiento Docker, exploraremos en profundidad cómo gestionar los datos: las diferencias entre volúmenes, bind mounts y tmpfs, los storage drivers y las estrategias de copia de seguridad y restauración.
Docker: De Principiante a Avanzado
Módulo 1: Introducción a Docker
- ¿Qué es Docker?
- Instalando Docker
- Arquitectura de Docker
- Comandos Básicos de Docker
- Entendiendo las Imágenes de Docker
- Creando tu Primer Contenedor Docker
Módulo 2: Trabajando con Imágenes Docker
- Docker Hub y Repositorios
- Construyendo Imágenes Docker
- Conceptos Básicos de Dockerfile
- Gestionando Imágenes Docker
- Etiquetado y Publicación de Imágenes
Módulo 3: Contenedores Docker
- Ejecutando Contenedores
- Ciclo de Vida del Contenedor
- Gestionando Contenedores
- Redes en Docker
- Persistencia de Datos con Volúmenes
Módulo 4: Docker Compose
- Introducción a Docker Compose
- Definiendo Servicios en Docker Compose
- Comandos de Docker Compose
- Aplicaciones Multi-Contenedor
- Variables de Entorno en Docker Compose
Módulo 5: Conceptos Avanzados de Docker
- Profundización en Redes Docker
- Opciones de Almacenamiento Docker
- Mejores Prácticas de Seguridad en Docker
- Optimizando Imágenes Docker
- Registro y Monitoreo en Docker
Módulo 6: Docker en Producción
- CI/CD con Docker
- Orquestando Contenedores con Docker Swarm
- Introducción a Kubernetes
- Desplegando Contenedores Docker en Kubernetes
- Escalado y Balanceo de Carga
