Saltar al contenido principal
Volver al blog
· 16 min de lectura

Docker Networking: guía completa de modos de red con network_mode host

Guía completa de networking en Docker: modos de red (bridge, host, none, overlay, macvlan), ejemplos con docker run y Docker Compose, comparación de rendimiento, y troubleshooting de problemas comunes.

docker networking sre

Docker gestiona una capa de red propia que permite a los contenedores comunicarse entre sí y con el exterior de forma controlada. Entender los modos de red disponibles es fundamental para diseñar arquitecturas de contenedores seguras, eficientes y fáciles de depurar. Elegir el modo incorrecto puede introducir latencia innecesaria, problemas de aislamiento o conflictos de puertos difíciles de diagnosticar.

Este artículo cubre los cinco modos de red principales de Docker, con ejemplos prácticos usando docker run y Docker Compose. El foco central es network_mode: host, el modo que elimina la capa de abstracción de red y ofrece el máximo rendimiento, junto con una comparación detallada frente a los demás modos disponibles.

Conceptos fundamentales

Cuando Docker Engine se instala en un host Linux, crea una infraestructura de red virtual que aísla los contenedores del sistema anfitrión. Cada contenedor obtiene su propio stack de red (interfaces, tabla de enrutamiento, reglas de firewall) dentro de un namespace de red independiente. Docker Engine se encarga de crear y gestionar las interfaces virtuales, asignar direcciones IP y configurar las reglas de NAT necesarias para el tráfico saliente.

Arquitectura de red de Docker

Al instalarse, Docker crea una interfaz de red virtual llamada docker0, que actúa como un bridge (puente) de red entre los contenedores y el host. Los componentes principales de esta arquitectura son:

  • docker0 — interfaz bridge por defecto. Funciona como un switch virtual al que se conectan los contenedores.
  • veth pairs — pares de interfaces virtuales Ethernet. Un extremo se conecta al namespace de red del contenedor y el otro al bridge docker0.
  • Namespaces de red — cada contenedor se ejecuta dentro de su propio namespace de red aislado, con su propia interfaz eth0, dirección IP y tabla de enrutamiento.
  • DNS interno (127.0.0.11) — Docker ejecuta un servidor DNS embebido que permite a los contenedores en redes personalizadas resolver nombres de otros contenedores automáticamente.
# Ver las redes disponibles en Docker
docker network ls

# Inspeccionar la red bridge por defecto
docker network inspect bridge

La salida de docker network inspect bridge muestra la subred asignada, la puerta de enlace y los contenedores conectados a esa red.

Modos de red en Docker

Docker ofrece cinco modos de red (drivers), cada uno diseñado para un escenario específico. La elección del modo depende de los requisitos de aislamiento, rendimiento y topología del despliegue.

ModoDriverAislamientoRendimientoCaso de uso principal
bridgebridgeAltoMedioContenedores independientes en un solo host
hosthostNingunoMáximoAplicaciones sensibles a latencia
nonenullTotalN/AContenedores sin red, procesamiento offline
overlayoverlayAltoMedioComunicación multi-host (Swarm)
macvlanmacvlanMedioAltoContenedores con MAC/IP propia en la red física

Red bridge (por defecto)

El modo bridge es el que Docker asigna por defecto a todos los contenedores cuando no se especifica otro. Los contenedores conectados a un bridge comparten una subred virtual y pueden comunicarse entre sí a través de la interfaz docker0. El tráfico hacia el exterior pasa por NAT.

Existen dos variantes de bridge: la red por defecto y las redes bridge personalizadas. La diferencia principal es que las redes personalizadas habilitan la resolución DNS automática por nombre de contenedor.

Bridge por defecto

Al ejecutar un contenedor sin especificar red, Docker lo conecta a la red bridge por defecto:

# Ejecutar un contenedor en la red bridge por defecto
docker run -d --name web -p 8080:80 nginx

En Docker Compose, este comportamiento se obtiene sin configuración adicional de red. Compose crea automáticamente una red bridge personalizada para el proyecto:

services:
  web:
    image: nginx
    ports:
      - '8080:80'

En la red bridge por defecto, los contenedores solo pueden comunicarse entre sí usando direcciones IP. No hay resolución DNS por nombre de contenedor.

Bridge personalizada

Las redes bridge personalizadas son la opción recomendada para la mayoría de despliegues en un solo host:

# Crear una red bridge personalizada
docker network create mi-red

# Ejecutar contenedores en esa red
docker run -d --name app --network mi-red nginx
docker run -d --name db --network mi-red postgres:16

# Verificar la comunicación por nombre
docker exec app ping db

En Docker Compose, se declaran redes personalizadas en la sección networks:

services:
  app:
    image: nginx
    networks:
      - backend
    ports:
      - '8080:80'

  db:
    image: postgres:16
    networks:
      - backend
    environment:
      POSTGRES_PASSWORD: secreto

networks:
  backend:
    driver: bridge
CaracterísticaBridge por defectoBridge personalizada
Resolución DNS por nombreNo
Aislamiento entre contenedoresCompartida con todosSolo contenedores en la misma red
Configuración de subredAutomáticaConfigurable
Comunicación entre contenedoresSolo por IPPor nombre de contenedor/servicio

Red host (network_mode: host)

El modo host es el que ofrece el mayor rendimiento de red en Docker. Elimina completamente la capa de virtualización de red y permite al contenedor usar directamente el stack de red del host.

Cómo funciona

Cuando un contenedor se ejecuta con --network host, Docker no crea un namespace de red independiente para ese contenedor. En su lugar, el contenedor comparte directamente el namespace de red del sistema anfitrión. Esto significa que:

  • No se crea una interfaz docker0 para ese contenedor.
  • No se generan veth pairs.
  • No hay traducción de direcciones (NAT).
  • El contenedor ve las mismas interfaces de red que el host (eth0, lo, wlan0, etc.).
  • Los puertos que el contenedor abre están directamente expuestos en el host.

Si el contenedor inicia un servidor en el puerto 80, ese puerto queda abierto directamente en la IP del host, sin necesidad de port mapping (-p).

Cuándo usar host mode

  • Aplicaciones sensibles a latencia — la ausencia de NAT y veth pairs elimina la latencia adicional que introduce el modo bridge.
  • Servicios que necesitan acceso a todas las interfaces del host — herramientas de monitoreo de red como Prometheus node_exporter, cAdvisor o tcpdump que requieren visibilidad completa del stack de red.
  • Rendimiento de red máximo — benchmarks y aplicaciones donde el throughput es crítico y cada microsegundo cuenta.
  • Servicios con rangos de puertos dinámicos — aplicaciones que abren puertos efímeros o que utilizan rangos amplios de puertos, donde el mapeo estático de -p resulta impráctico.

Ejemplos con docker run

Ejecutar un servidor web Nginx directamente en el stack de red del host:

# Ejecutar Nginx en modo host
docker run -d --network host --name web nginx

# Verificar que responde en el puerto 80 del host
curl http://localhost:80

Ejecutar una herramienta de monitoreo que necesita acceso a las interfaces del host:

# Ejecutar Prometheus node_exporter en modo host
docker run -d --network host --name node-exporter prom/node-exporter

# Verificar las métricas en el puerto 9100
curl http://localhost:9100/metrics

Ejemplos con Docker Compose

En Docker Compose, el modo host se configura con la directiva network_mode:

services:
  web:
    image: nginx
    network_mode: host

Para un escenario con monitoreo:

services:
  node-exporter:
    image: prom/node-exporter
    network_mode: host
    restart: unless-stopped

Nota: al usar network_mode: host, la directiva ports: se ignora. Docker no realiza port mapping porque el contenedor ya usa directamente los puertos del host.

Limitaciones

  • No funciona en Docker Desktop (macOS/Windows) — Docker Desktop ejecuta los contenedores dentro de una máquina virtual Linux. El modo host expone los puertos dentro de esa VM, no en el sistema operativo anfitrión.
  • Sin aislamiento de puertos — si el host ya tiene un servicio escuchando en el puerto 80 y el contenedor intenta usar el mismo puerto, se produce un error bind: address already in use.
  • Sin port mapping — la directiva ports: en Docker Compose o -p en docker run se ignora completamente. No es posible remapear puertos.
  • Menor seguridad — el contenedor tiene acceso completo al stack de red del host, incluyendo todas las interfaces, puertos abiertos y tráfico de red. Esto aumenta la superficie de ataque.

Red none

El modo none desactiva completamente la red del contenedor. El contenedor solo tiene acceso a la interfaz de loopback (lo). Es útil para cargas de trabajo que no necesitan comunicación de red, como procesamiento de archivos en batch o tareas de cómputo aisladas.

# Ejecutar un contenedor sin red
docker run -d --network none --name batch alpine sleep 3600

# Verificar que solo existe la interfaz loopback
docker exec batch ip addr

La salida de ip addr muestra únicamente la interfaz lo con la dirección 127.0.0.1.

En Docker Compose:

services:
  batch:
    image: alpine
    network_mode: none
    command: sleep 3600

Red overlay

El modo overlay permite la comunicación entre contenedores que se ejecutan en diferentes hosts físicos. Es el driver utilizado por Docker Swarm para crear redes que abarcan múltiples nodos del cluster. El tráfico entre hosts se encapsula usando VXLAN (Virtual Extensible LAN).

Crear una red overlay requiere que el host esté en modo Swarm:

# Inicializar Docker Swarm
docker swarm init

# Crear una red overlay
docker network create -d overlay mi-overlay

# Crear un servicio que use la red overlay
docker service create --name web --network mi-overlay --replicas 3 nginx

En Docker Compose, las redes overlay se declaran con el driver correspondiente. Este archivo está diseñado para desplegarse con docker stack deploy:

services:
  web:
    image: nginx
    networks:
      - mi-overlay
    deploy:
      replicas: 3

networks:
  mi-overlay:
    driver: overlay

La red overlay introduce latencia adicional por la encapsulación VXLAN, pero es la única opción nativa de Docker para comunicación multi-host sin herramientas externas.

Red macvlan

El modo macvlan asigna una dirección MAC y una dirección IP de la red física directamente al contenedor. Desde la perspectiva de la red, el contenedor aparece como un dispositivo físico más conectado al switch. Es útil cuando los contenedores necesitan ser accesibles directamente desde la red local sin NAT ni port mapping.

# Crear una red macvlan
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  mi-macvlan

# Ejecutar un contenedor con IP fija en la red física
docker run -d --network mi-macvlan --ip 192.168.1.100 --name servidor nginx

En Docker Compose:

services:
  servidor:
    image: nginx
    networks:
      mi-macvlan:
        ipv4_address: 192.168.1.100

networks:
  mi-macvlan:
    driver: macvlan
    driver_opts:
      parent: eth0
    ipam:
      config:
        - subnet: 192.168.1.0/24
          gateway: 192.168.1.1

Nota: en la mayoría de configuraciones, el host no puede comunicarse directamente con los contenedores macvlan a través de la interfaz padre (eth0). Esto es una limitación del kernel de Linux. Para habilitar esta comunicación, es necesario crear una subinterfaz macvlan en el host.

Comparación de rendimiento

Característicabridgehostnoneoverlaymacvlan
Overhead de NATNoN/ANo
Latencia adicionalBajaNingunaN/AMedia (VXLAN)Muy baja
ThroughputMedioMáximoN/AMedioAlto
Port mappingSí (-p)NoN/ASí (-p)No
Resolución DNS internaSí (custom)NoNoSí (custom)
Múltiples hostsNoNoNoNo

El modo host ofrece el mejor rendimiento al eliminar todas las capas de abstracción, pero sacrifica aislamiento. El modo bridge personalizado es el mejor equilibrio entre rendimiento y seguridad para la mayoría de escenarios en un solo host.

Comandos útiles para gestión de redes

ComandoDescripción
docker network lsLista todas las redes disponibles
docker network create mi-redCrea una red bridge personalizada
docker network create -d overlay mi-overlayCrea una red overlay (requiere Swarm)
docker network inspect mi-redMuestra la configuración detallada de una red
docker network connect mi-red contenedorConecta un contenedor en ejecución a una red
docker network disconnect mi-red contenedorDesconecta un contenedor de una red
docker network rm mi-redElimina una red (debe estar sin contenedores)
docker network pruneElimina todas las redes que no están en uso

Buenas prácticas

  • Usa redes bridge personalizadas en lugar de la red por defecto — las redes personalizadas habilitan resolución DNS por nombre, mejor aislamiento y configuración de subred.
  • Reserva el modo host exclusivamente para casos de rendimiento máximo — monitoreo de red, proxies de alto tráfico o aplicaciones donde la latencia del NAT es inaceptable.
  • Evita el modo host en Docker Desktop (macOS/Windows) — el modo host no se comporta como se espera porque Docker Desktop ejecuta los contenedores dentro de una VM.
  • No expongas puertos innecesarios en host mode — revisa la configuración del contenedor para asegurar que solo los puertos necesarios están en uso, ya que el host queda directamente expuesto.
  • Usa overlay solo cuando necesites comunicación multi-host — si todos los contenedores están en el mismo host, bridge personalizado ofrece mejor rendimiento que overlay.
  • Limpia redes huérfanas periódicamente con docker network prune — las redes sin uso acumulan recursos y dificultan la administración.
  • Documenta la topología de red del proyecto — incluye un diagrama o una tabla en el repositorio que describa qué servicios están en qué red y por qué.
  • Usa docker network inspect para depurar problemas de conectividad — este comando muestra la subred, puerta de enlace, contenedores conectados y su dirección IP asignada.
  • Asigna una red explícita a cada servicio en Docker Compose — evita depender de la red por defecto del proyecto. Declarar redes explícitamente hace la configuración más legible y predecible.
  • No mezcles network_mode: host con la directiva networks: — son mutuamente excluyentes. Docker Compose rechaza configuraciones que combinan ambas.

Troubleshooting

Conflicto de puertos en host mode

Al usar --network host, si el host ya tiene un proceso escuchando en el mismo puerto que el contenedor necesita, Docker no puede iniciarlo y muestra el error:

Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use

Para identificar qué proceso está usando el puerto:

# Identificar el proceso que ocupa el puerto
ss -tulnp | grep :80

La solución es detener el proceso que ocupa el puerto o cambiar el puerto que usa la aplicación dentro del contenedor.

Contenedores que no se comunican entre sí

Si dos contenedores no pueden comunicarse, verifica que estén conectados a la misma red:

# Inspeccionar las redes de un contenedor
docker inspect --format='{{json .NetworkSettings.Networks}}' app

# Conectar un contenedor a una red existente
docker network connect mi-red app

Si cada contenedor está en una red diferente, no tendrán visibilidad de red entre sí. Conecta ambos a una red compartida.

Fallo en resolución DNS entre contenedores

Si un contenedor no puede resolver el nombre de otro contenedor (por ejemplo, ping db falla con Name or service not known), la causa más probable es que ambos están en la red bridge por defecto, que no tiene resolución DNS.

La solución es crear una red bridge personalizada y conectar ambos contenedores a ella:

# Crear una red personalizada
docker network create app-net

# Ejecutar los contenedores en esa red
docker run -d --name app --network app-net nginx
docker run -d --name db --network app-net postgres:16

# Verificar la resolución DNS
docker exec app ping db

network_mode: host no funciona en Docker Desktop (macOS/Windows)

En Docker Desktop, los contenedores se ejecutan dentro de una máquina virtual Linux gestionada por Docker. Cuando se usa network_mode: host, el contenedor comparte el stack de red de esa VM, no del sistema operativo anfitrión. Esto significa que los puertos no son accesibles directamente desde macOS o Windows.

Advertencia: network_mode: host en Docker Desktop no expone los puertos en el sistema anfitrión. Usa la directiva ports: con el modo bridge para desarrollo local en macOS o Windows.

La alternativa para desarrollo local es usar port mapping convencional:

services:
  web:
    image: nginx
    ports:
      - '8080:80'

Contenedor con network_mode: host no accede a otros contenedores por nombre

Cuando un contenedor usa network_mode: host, no está conectado a ninguna red de Docker y no utiliza el servidor DNS interno de Docker (127.0.0.11). Esto significa que no puede resolver nombres de otros contenedores.

Para comunicarse con otros contenedores desde un contenedor en modo host, utiliza localhost:<puerto> si el otro contenedor también está en modo host, o la dirección IP del host si el otro contenedor expone puertos con -p:

# Desde un contenedor en modo host, acceder a otro servicio en el puerto 5432
curl http://localhost:5432

# O usar la IP del host
curl http://192.168.1.10:5432

Si necesitas resolución DNS por nombre entre servicios, el modo host no es adecuado. Usa una red bridge personalizada en su lugar.

Acceder a servicios del host desde un contenedor

Un escenario frecuente es necesitar que un contenedor en modo bridge se comunique con un servicio que se ejecuta directamente en la máquina host: una base de datos en desarrollo, una API local o cualquier otro proceso. El problema es que localhost dentro del contenedor se refiere al propio contenedor, no al host. Usar 127.0.0.1 tampoco funciona porque apunta al loopback del contenedor.

Docker provee el hostname especial host.docker.internal que resuelve a la IP interna del host. Esto permite que los contenedores accedan a servicios del host sin hardcodear direcciones IP que pueden cambiar.

Verificar la conectividad con el host desde un contenedor:

docker run --rm alpine ping host.docker.internal

En Docker Compose, se puede usar host.docker.internal directamente en las variables de entorno para apuntar a servicios del host:

services:
  app:
    image: node:22-alpine
    environment:
      API_URL: http://host.docker.internal:3000

En este ejemplo, el contenedor app hace peticiones a una API que se ejecuta en el puerto 3000 del host.

Nota: la compatibilidad de host.docker.internal varía según la plataforma:

  • Docker Desktop (macOS/Windows): funciona nativamente sin configuración adicional.
  • Linux: host.docker.internal no se resuelve por defecto. Es necesario agregarlo explícitamente.

En Linux, hay que usar la flag --add-host en docker run:

docker run --rm --add-host host.docker.internal:host-gateway alpine ping host.docker.internal

O la directiva extra_hosts en Docker Compose:

services:
  app:
    image: node:22-alpine
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    environment:
      API_URL: http://host.docker.internal:3000

Nota: host-gateway es un valor especial que Docker reemplaza automáticamente por la IP real del host en el momento de crear el contenedor. No es necesario conocer ni hardcodear la dirección IP del host.