Redes en Docker: bridge, host y redes personalizadas
Índice de contenidos
- Puntos clave
- ¿Qué tipos de red ofrece Docker?
- La red bridge por defecto y sus límites
- Redes bridge personalizadas y DNS interno
- La red host y la red none
- Cómo conectar varios servicios en Docker Compose
- Publicar puertos frente a exponer
- Preguntas frecuentes
- ¿Puedo comunicar dos contenedores por su nombre en la red bridge por defecto?
- ¿Cuándo debo usar la red host en lugar de bridge?
- ¿Qué diferencia hay entre publicar un puerto y exponerlo?
- Conclusión
- Fuentes
Docker ofrece seis tipos de red: bridge, host, none, overlay, macvlan e ipvlan. La red bridge por defecto conecta contenedores por IP, pero sin resolución de nombres. Una red bridge personalizada añade un DNS interno para que los servicios se localicen por su nombre, y es la opción recomendada para casi cualquier despliegue.
Cuando arrancas tu primer contenedor con Docker, la red simplemente funciona: el proceso sale a internet y tú publicas un puerto para llegar a él. El problema aparece cuando montas dos o tres servicios y descubres que uno no ve al otro por su nombre. En esta guía repaso los tipos de red que ofrece Docker, por qué la red por defecto se queda corta y cómo montar redes personalizadas que resuelven nombres solas, con un docker-compose.yml listo para copiar.
Puntos clave
- Docker trae seis drivers de red:
bridge,host,none,overlay,macvlaneipvlan. Para un servidor con un solo host, los tres primeros cubren casi todo. - La red
bridgepor defecto conecta contenedores por IP en el rango172.17.0.0/16, pero no resuelve nombres entre ellos. - Una red
bridgepersonalizada añade un DNS interno: los contenedores se localizan por su nombre, que es justo lo que necesitas para que una app hable con su base de datos. - La red
hostelimina la capa de aislamiento y comparte la pila de red del anfitrión; la rednonedeja al contenedor sin red. - Docker Compose crea una red personalizada por proyecto de forma automática y cada servicio es accesible por su nombre de servicio.
¿Qué tipos de red ofrece Docker?
Docker gestiona la red mediante drivers intercambiables. En una instalación estándar tienes seis incorporados, y cada uno resuelve un escenario distinto:
- bridge: el driver por defecto. Crea una red privada virtual en el anfitrión y conecta a ella los contenedores. Es lo que quieres en un servidor con un único host.
- host: el contenedor usa directamente la pila de red del anfitrión, sin NAT ni traducción de puertos.
- none: sin red. El contenedor solo tiene su interfaz de loopback.
- overlay: conecta contenedores repartidos por varios anfitriones, la base de Docker Swarm.
- macvlan e ipvlan: dan a cada contenedor una dirección MAC o IP propia en tu red física, útil para servicios que deben aparecer como un equipo más de la LAN.
Puedes verlas con un comando. Al instalar Docker (si aún no lo has hecho, sigue la guía de instalación en Ubuntu 24.04), ya existen tres redes de arranque:
docker network ls
El resultado muestra bridge, host y none. Estas tres son las que usarás casi siempre en un homelab o en un VPS.
La red bridge por defecto y sus límites
Cuando lanzas un contenedor sin indicar red, Docker lo engancha a la red bridge por defecto, asociada a la interfaz docker0 del anfitrión. Cada contenedor recibe una IP dentro de 172.17.0.0/16 y sale a internet a través de la puerta de enlace 172.17.0.1 mediante NAT. Hasta aquí, bien.
El límite aparece con la resolución de nombres. En la red por defecto, un contenedor no puede llamar a otro por su nombre: solo llega por su IP, que además cambia en cada arranque. La única forma antigua de enlazarlos era la opción --link, hoy obsoleta y desaconsejada. Por eso montar una app y su base de datos en la red por defecto es una fuente segura de dolores de cabeza.
Hay un detalle de seguridad que conviene recordar. Desde Docker Engine v28 (marzo de 2025), el motor descarta por defecto el tráfico entrante no solicitado hacia la IP interna de un contenedor salvo que hayas publicado el puerto de forma explícita. En la práctica, un puerto sin publicar dejó de ser accesible desde otros equipos de la red local, un endurecimiento que agradecerás.
Redes bridge personalizadas y DNS interno
La solución al problema de los nombres es crear tu propia red bridge. La diferencia es enorme: en una red personalizada, Docker levanta un servidor DNS interno que resuelve los nombres de los contenedores de forma automática. Si tienes un contenedor llamado db, cualquier otro contenedor de la misma red lo alcanza escribiendo db como si fuera un nombre de dominio.
Crear una red y conectar contenedores a ella es directo:
docker network create --driver bridge mi_red
docker run -d --name db --network mi_red postgres:17
docker run -d --name web --network mi_red nginx:1.29
Ahora el contenedor web puede conectarse a db:5432 sin conocer ninguna IP. Además de la resolución de nombres, una red personalizada mejora el aislamiento (solo los contenedores que conectes a ella se ven entre sí) y te permite conectar y desconectar contenedores en caliente. Para cualquier despliegue con más de un servicio, esta es la opción por defecto que deberías tomar.
La red host y la red none
El driver host quita la capa intermedia: el contenedor comparte directamente la pila de red del anfitrión. No hay NAT ni puertos publicados, porque el contenedor escucha en los puertos del propio servidor. Es útil para un servicio que necesita máximo rendimiento de red o que abre muchos puertos, como un servidor de VPN o un descubridor de dispositivos en la LAN. A cambio, pierdes aislamiento: si el contenedor abre el puerto 8080, lo abre en el anfitrión.
Un aviso importante: el driver host es nativo en Docker Engine sobre Linux. En Docker Desktop solo funciona desde la versión 4.34, hay que activarlo en los ajustes, opera a nivel 4 y únicamente con contenedores Linux. Si desarrollas en Mac o Windows, tenlo en cuenta antes de depender de él.
En el extremo contrario está none: el contenedor arranca sin ninguna interfaz de red salvo el loopback. Nadie entra y él no sale. Sirve para tareas de procesamiento puro que no deben tocar la red, como un trabajo por lotes que solo lee y escribe en un volumen montado.
Cómo conectar varios servicios en Docker Compose
Aquí es donde todo encaja. Cuando ejecutas docker compose up, Docker crea de forma automática una red bridge personalizada para el proyecto y conecta a ella todos los servicios. Cada servicio es accesible por su nombre de servicio, sin que tengas que crear la red a mano.
Este docker-compose.yml monta una app web y una base de datos PostgreSQL en dos redes segmentadas: la app está en frontend y backend, la base de datos solo en backend, y esa red interna no tiene salida a internet.
services:
app:
image: nginx:1.29
restart: unless-stopped
ports:
- "8080:80"
networks:
- frontend
- backend
depends_on:
db:
condition: service_healthy
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_PASSWORD: cambia_esta_clave
volumes:
- db_data:/var/lib/postgresql/data
networks:
- backend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
frontend:
backend:
internal: true
volumes:
db_data:
Arráncalo con un comando y comprueba la red que se ha creado:
docker compose up -d
docker network inspect $(basename $PWD)_backend
La app llega a la base de datos como db:5432 gracias al DNS interno. Como db no está en frontend y backend está marcada como internal, la base de datos queda aislada: no publica ningún puerto y no tiene salida a internet. Solo app publica el puerto 8080. Este patrón de segmentar redes es la base para colocar después un proxy inverso como Traefik delante de la app sin exponer nunca la base de datos.
Publicar puertos frente a exponer
Es la confusión más habitual en las redes de Docker. Publicar y exponer no son lo mismo:
- Publicar (
ports:en Compose,-p HOST:CONTENEDORen la línea de comandos) mapea un puerto del contenedor a un puerto del anfitrión. Ese puerto queda accesible desde fuera de Docker."8080:80"significa que el puerto 80 del contenedor responde en el 8080 del servidor. - Exponer (
expose:en Compose,EXPOSEen el Dockerfile) solo documenta que el contenedor escucha en un puerto, para consumo interno entre contenedores. No abre nada hacia el anfitrión.
Un matiz de seguridad: publicar un puerto lo enlaza a 0.0.0.0 por defecto, es decir, a todas las interfaces. Si un servicio solo debe ser accesible desde el propio servidor (por ejemplo, un panel de administración detrás de un proxy), publícalo solo en la máquina local con 127.0.0.1:8080:80 en lugar de 8080:80. Así el puerto no queda abierto a la red.
Preguntas frecuentes
¿Puedo comunicar dos contenedores por su nombre en la red bridge por defecto?
No. La red bridge por defecto no incluye resolución de nombres, así que un contenedor solo alcanza a otro por su IP, y esa IP cambia en cada arranque. Crea una red bridge personalizada con docker network create y conecta ambos contenedores a ella: entonces se localizan por su nombre gracias al DNS interno de Docker.
¿Cuándo debo usar la red host en lugar de bridge?
Usa host cuando el servicio necesite el máximo rendimiento de red o abra muchísimos puertos, como una VPN o un sistema de domótica que descubre dispositivos por la LAN. Para el resto de casos, una red bridge personalizada es más segura porque aísla el contenedor y te deja controlar qué puertos publicas.
¿Qué diferencia hay entre publicar un puerto y exponerlo?
Publicar (-p o ports:) abre el puerto hacia el anfitrión y lo hace accesible desde fuera. Exponer (EXPOSE o expose:) es solo documentación: indica en qué puerto escucha el contenedor para que otros contenedores lo usen, pero no lo abre al anfitrión. Para llegar a un servicio desde tu navegador, necesitas publicarlo.
Conclusión
Las redes de Docker se entienden mucho mejor con una regla sencilla: la red bridge por defecto vale para pruebas rápidas de un solo contenedor, pero en cuanto tienes dos servicios que deben hablar entre sí, crea una red bridge personalizada y deja que el DNS interno haga el trabajo. Con Docker Compose eso es automático, y segmentar redes (una pública y una interna) te da aislamiento gratis. El siguiente paso natural es la persistencia de datos: cómo hacer que lo que guardan tus contenedores sobreviva a un reinicio con volúmenes y bind mounts.
También disponible en inglés: Docker networking.