Docker networking: bridge, host, overlay, redes personalizadas, mapeo de puertos y DNS en contenedores

Docker networking: bridge, host, overlay, redes personalizadas, mapeo de puertos y DNS en contenedores

[!tip] Networking Docker en una frase Docker networking es el sistema que permite a los contenedores comunicarse entre sΓ­ y con el mundo exterior. Por defecto usa redes bridge con NAT, pero tambiΓ©n soporta redes host, overlay para Swarm/Kubernetes, y redes personalizadas con DNS automΓ‘tico.

ΒΏPor quΓ© networking Docker es diferente?

Los contenedores son procesos aislados β€” cada uno tiene su propio namespace de red, su propio conjunto de interfaces, su propio espacio de direcciones IP. Esto hace que la networking de Docker sea un problema ΓΊnico de resolver.

Contenedor A                    Host                    Contenedor B
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  PID Namespace    β”‚      β”‚  PID Namespace    β”‚      β”‚  PID Namespace    β”‚
β”‚  Network Namespace β”‚      β”‚  Network Namespaceβ”‚      β”‚  Network Namespaceβ”‚
β”‚                  β”‚      β”‚                  β”‚      β”‚                  β”‚
β”‚  eth0: 172.17.0.2β”‚      β”‚  eth0: 10.0.0.1   β”‚      β”‚  eth0: 172.17.0.3β”‚
β”‚  IP: 172.17.0.2  β”‚      β”‚  IP: 10.0.0.1     β”‚      β”‚  IP: 172.17.0.3  β”‚
β”‚  Puerto 3000     β”‚      β”‚  Puerto 8080:3000 β”‚      β”‚  Puerto 5432     β”‚
β”‚                  β”‚      β”‚  iptables NAT     β”‚      β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                        β”‚                        β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                           docker0 bridge (172.17.0.1)

Tipos de redes Docker

1. Red bridge (por defecto)

La red bridge es el modo de red por defecto de Docker. Crea una pasarela virtual para cada host Docker.

Red bridge por defecto (docker0):

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Host: 10.0.2.15                     docker0: 172.17.0.1/16          β”‚
β”‚  eth0: 10.0.2.15 ───┐                                               β”‚
β”‚                     β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚                     └────────│ docker0 bridge                    β”‚    β”‚
β”‚                              β”‚ 172.17.0.1 (gateway)             β”‚    β”‚
β”‚                              β”‚                                  β”‚    β”‚
β”‚                              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚    β”‚
β”‚                              β”‚  β”‚ container: web    β”‚           β”‚    β”‚
β”‚                              β”‚  β”‚  172.17.0.2      β”‚           β”‚    β”‚
β”‚                              β”‚  β”‚  eth0: eth0       β”‚           β”‚    β”‚
β”‚                              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚    β”‚
β”‚                              β”‚                                  β”‚    β”‚
β”‚                              β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚    β”‚
β”‚                              β”‚  β”‚ container: db     β”‚           β”‚    β”‚
β”‚                              β”‚  β”‚  172.17.0.3       β”‚           β”‚    β”‚
β”‚                              β”‚  β”‚  eth0: eth0       β”‚           β”‚    β”‚
β”‚                              β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚    β”‚
β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                      β”‚
β”‚  iptables (NAT):                                                     β”‚
β”‚  PREROUTING: docker0 β†’ contenedores                                 β”‚
β”‚  POSTROUTING: contenedores β†’ host (MASCARADA)                       β”‚
β”‚  FORWARD: host ↔ contenedores                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
# Ver la red bridge por defecto
docker network ls
# NETWORK ID  NAME      DRIVER    SCOPE
# abc123      bridge    bridge    local
# def456      host      host      local
# ghi789      none      null      local
 
# Inspeccionar la red bridge
docker network inspect bridge
# [
#   {
#     "Name": "bridge",
#     "Driver": "bridge",
#     "IPAM": {
#       "Config": [{"Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1"}]
#     }
#   }
# ]
 
# Los contenedores conectados a la red bridge
# Se comunican con IPs como 172.17.0.x
# NO se comunican por nombre (sin red personalizada)
CaracterΓ­sticas de la red bridge por defecto:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CaracterΓ­stica     β”‚  Detalle                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Driver             β”‚  bridge (iptables)                   β”‚
β”‚  Subnet             β”‚  172.17.0.0/16 (por defecto)         β”‚
β”‚  Gateway            β”‚  172.17.0.1                          β”‚
β”‚  DNS interno        β”‚  ❌ No (no resuelve nombres)         β”‚
β”‚  ComunicaciΓ³n       β”‚  Solo por IP                         β”‚
β”‚  Aislamiento        β”‚  Alto (necesita --network)           β”‚
β”‚  Puerto mapeo       β”‚  -p flag                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Red bridge personalizada (RECOMENDADA)

Las redes bridge personalizadas resuelven el problema de DNS interno de la red bridge por defecto:

# Crear una red bridge personalizada con subnet especΓ­fica
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  --opt com.docker.network.bridge.name=br-myapp \
  myapp-network
 
# Conectar servicios a la red
docker run -d --name web --network myapp-network nginx:latest
docker run -d --name db --network myapp-network postgres:16
# web y db pueden comunicarse por NOMBRE: db responde a "db", web responde a "web"
DNS en red bridge personalizada:
─────────────────────────────────

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  myapp-network (bridge personalizado)         β”‚
β”‚                                              β”‚
β”‚  web (172.20.0.2) ──DNS──▢ 172.20.0.3 (db)   β”‚
β”‚    β”‚                                      β”‚   β”‚
β”‚    β”‚ host: db                              β”‚   β”‚
β”‚    β”‚ host: 172.20.0.3                      β”‚   β”‚
β”‚    β”‚                                       β”‚   β”‚
β”‚  api (172.20.0.4) ──DNS──▢ 172.20.0.3 (db)  β”‚
β”‚    β”‚                                      β”‚   β”‚
β”‚    β”‚ host: db                              β”‚   β”‚
β”‚    β”‚                                       β”‚   β”‚
β”‚  cache (172.20.0.5)                        β”‚   β”‚
β”‚    β”‚ host: db                              β”‚   β”‚
β”‚    β”‚ host: web                             β”‚   β”‚
β”‚    β”‚ host: api                             β”‚   β”‚
β”‚    β”‚ host: cache                           β”‚   β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

⚑ Los nombres de los contenedores se resuelven automÑticamente
   a sus IPs en la red. No necesitas configurar DNS manualmente.
# docker-compose.yml con red personalizada
services:
  web:
    image: nginx:latest
    networks:
      - myapp-net
    ports:
      - "80:80"
 
  api:
    image: my-api:latest
    environment:
      DATABASE_URL: postgresql://user:pass@db:5432/mydb
    networks:
      - myapp-net
 
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    networks:
      - myapp-net
 
networks:
  myapp-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.25.0.0/16

3. Red host

La red host comparte la red del host directamente. No hay aislamiento de red ni NAT:

# Red host: el contenedor usa la red del host directamente
docker run -d --network host nginx:latest
# Nginx escucha en el puerto 80 del HOST directamente
# http://localhost:80 β†’ nginx en el host (sin mapeo de puertos)
 
# ⚠️ Con host networking NO se usa -p (mapeo de puertos)
# docker run -d --network host -p 8080:80 nginx:latest
# Esto da ERROR porque --network host ignora -p
ComparaciΓ³n host vs bridge:

REDA HOST:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Host Server: 10.0.2.15            β”‚
β”‚                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Container: nginx            β”‚  β”‚  ← Misma red que el host
β”‚  β”‚  Puerto: 80 (directo)        β”‚  β”‚  ← Sin NAT, sin bridge
β”‚  β”‚  IP: 10.0.2.15 (la del host) β”‚  β”‚  ← Misma IP
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                     β”‚
β”‚  http://10.0.2.15:80 β†’ nginx       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

REDA BRIDGE (por defecto):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Host Server: 10.0.2.15                    β”‚
β”‚                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
β”‚  β”‚  docker0 bridge: 172.17.0.1/16    β”‚     β”‚
β”‚  β”‚                                    β”‚     β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚     β”‚
β”‚  β”‚  β”‚  Container: nginx        β”‚     β”‚     β”‚
β”‚  β”‚  β”‚  IP: 172.17.0.2          β”‚     β”‚     β”‚
β”‚  β”‚  β”‚  Puerto: 80              β”‚     β”‚     β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚     β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚                                             β”‚
β”‚  iptables -t nat:                           β”‚
β”‚  :8080 β†’ :172.17.0.2:80                    β”‚
β”‚                                             β”‚
β”‚  http://10.0.2.15:8080 β†’ nginx             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
CuΓ‘ndo usar host networking:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Caso               β”‚  ΒΏUsar host?                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  API web estΓ‘ndar   β”‚  ❌ bridge + -p                    β”‚
β”‚  Base de datos      β”‚  ❌ bridge (o host si mΓ‘ximo perf) β”‚
β”‚  mΓ‘ximo rendimiento β”‚  βœ… host (evita NAT)               β”‚
β”‚  mΓΊltiples cont.    β”‚  ❌ host (colisiΓ³n de puertos)     β”‚
β”‚  networking         β”‚                                    β”‚
β”‚  Contenedor         β”‚  βœ… host (sin NAT overhead)      β”‚
β”‚  de logging/        β”‚                                    β”‚
β”‚  monitoreo          β”‚                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Ventajas host:
  - Cero overhead de red (sin NAT, sin bridge)
  - Acceso directo a interfaces de red del host
  - IP real visible en logs (sin IP de bridge)

Desventajas host:
  - No hay aislamiento de red
  - ColisiΓ³n de puertos (no puedes tener 2 servicios en el puerto 80)
  - No se puede usar -p con --network host
  - Riesgo de seguridad (contenedor ve toda la red del host)

4. Red none

La red none elimina toda la red del contenedor:

# Sin red
docker run -d --network none alpine:3.19
# El contenedor tiene NO interfaz de red en absoluto
 
# Para debugging: cuando necesitas ejecutar un contenedor
# sin acceso a la red (ej: procesar datos offline)
 
# Para aΓ±adir red manualmente despuΓ©s:
docker run -d --network none --name my-container alpine:3.19
# ... configurar manualmente la red despuΓ©s ...

5. Red overlay (Docker Swarm)

Las redes overlay conectan contenedores en diferentes hosts de un cluster Swarm:

Cluster Swarm con 3 nodos:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Node 1            β”‚     β”‚  Node 2            β”‚     β”‚  Node 3            β”‚
β”‚  10.0.1.10         β”‚     β”‚  10.0.1.20         β”‚     β”‚  10.0.1.30         β”‚
β”‚                    β”‚     β”‚                    β”‚     β”‚                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ container    β”‚  β”‚     β”‚  β”‚ container    β”‚  β”‚     β”‚  β”‚ container    β”‚  β”‚
β”‚  β”‚ web:1        β”‚  β”‚     β”‚  β”‚ web:2        β”‚  β”‚     β”‚  β”‚ web:3        β”‚  β”‚
β”‚  β”‚ 10.0.96.2    β”‚  β”‚     β”‚  β”‚ 10.0.96.3    β”‚  β”‚     β”‚  β”‚ 10.0.96.4    β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                    β”‚     β”‚                    β”‚     β”‚                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ container    β”‚  β”‚     β”‚  β”‚ container    β”‚  β”‚     β”‚  β”‚ container    β”‚  β”‚
β”‚  β”‚ db:1         β”‚  β”‚     β”‚  β”‚ db:2         β”‚  β”‚     β”‚  β”‚ db:3         β”‚  β”‚
β”‚  β”‚ 10.0.97.2    β”‚  β”‚     β”‚  β”‚ 10.0.97.3    β”‚  β”‚     β”‚  β”‚ 10.0.97.4    β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                          β”‚                          β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                           β”‚  Overlay Network β”‚
                           β”‚  myapp-overlay   β”‚
                           β”‚  (red virtual    β”‚
                           β”‚   sobre la       β”‚
                           β”‚   infraestructura)β”‚
                           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
# Crear un cluster Swarm
docker swarm init --advertise-addr 10.0.1.10
docker swarm join --token <token> 10.0.1.10:2377
 
# Crear red overlay (disponible en todos los nodos)
docker network create \
  --driver overlay \
  --attachable \
  myapp-overlay
 
# Ahora los contenedores en cualquier nodo
# pueden comunicarse a travΓ©s de esta red overlay
Overlay vs Bridge:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CaracterΓ­stica     β”‚  Bridge      β”‚  Overlay     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Scope              β”‚  Un solo     β”‚  Multi-node  β”‚
β”‚                     β”‚  host        β”‚  (Swarm)     β”‚
β”‚  Uso                β”‚  docker      β”‚  Docker      β”‚
β”‚                     β”‚  compose /   β”‚  Swarm       β”‚
β”‚                     β”‚  docker run  β”‚              β”‚
β”‚  ComunicaciΓ³n       β”‚  IP/Nombre   β”‚  IP/Nombre   β”‚
β”‚  Inter-host         β”‚  ❌ No       β”‚  βœ… SΓ­       β”‚
β”‚  Encapsulamiento    β”‚  No          β”‚  VXLAN       β”‚
β”‚  Complejidad        β”‚  Baja        β”‚  Media       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Mapeo de puertos

El sistema de puertos Docker

El mapeo de puertos conecta el puerto del contenedor con el puerto del host:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Host: 192.168.1.100                                           β”‚
β”‚                                                                 β”‚
β”‚  docker0 bridge: 172.17.0.1                                    β”‚
β”‚                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  iptables NAT Rules (resumen):                            β”‚  β”‚
β”‚  β”‚                                                          β”‚  β”‚
β”‚  β”‚  PREROUTING (DNAT):                                      β”‚  β”‚
β”‚  β”‚    -j DOCKER ! -i docker0                                β”‚  β”‚
β”‚  β”‚      -p tcp --dport 8080 -> 172.17.0.2:80               β”‚  β”‚
β”‚  β”‚    -j DOCKER ! -i docker0                                β”‚  β”‚
β”‚  β”‚      -p tcp --dport 3000 -> 172.17.0.3:3000             β”‚  β”‚
β”‚  β”‚    -j DOCKER ! -i docker0                                β”‚  β”‚
β”‚  β”‚      -p tcp --dport 5432 -> 172.17.0.4:5432             β”‚  β”‚
β”‚  β”‚                                                          β”‚  β”‚
β”‚  β”‚  POSTROUTING (MASQUERADE):                               β”‚  β”‚
β”‚  β”‚    -s 172.17.0.0/16 -o eth0 -j MASQUERADE               β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                                 β”‚
β”‚  Acceso:                                                        β”‚
β”‚  http://192.168.1.100:8080 β†’ nginx en 172.17.0.2:80           β”‚
β”‚  http://192.168.1.100:3000 β†’ api en 172.17.0.3:3000           β”‚
β”‚  psql -h 192.168.1.100 -p 5432 β†’ postgres en 172.17.0.4:5432  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
# Sintaxis: -p [host-ip:]host-port:container-port[/protocol]
docker run -d -p 8080:80 nginx:latest
#           ↑          ↑     ↑
#           β”‚          β”‚     └── Puerto del contenedor
#           β”‚          └── Puerto del host (si no se especifica IP, escucha en todas)
#           └── IP del host (opcional)
 
# Puerto especΓ­fico de host IP
docker run -d -p 127.0.0.1:8080:80 nginx:latest
# Solo accesible desde localhost, no desde la red externa
 
# Puerto UDP
docker run -d -p 5353:53/udp nginx:latest
 
# Rango de puertos del host
docker run -d -p 8000-8010:80 nginx:latest
# ⚠️ No recomendado β€” usa puertos individuales
 
# Puerto aleatorio del host (ΓΊtil para pruebas)
docker run -d -p 80 nginx:latest
# Docker asigna un puerto aleatorio. Verlo con:
docker port <container-name>
# Ejemplo de salida: 80/tcp -> 0.0.0.0:49153

Escenarios comunes de mapeo de puertos

# Escenario 1: API interna (solo localhost)
docker run -d -p 127.0.0.1:3000:3000 my-api:latest
# Solo accesible desde la mΓ‘quina local
 
# Escenario 2: API pΓΊblica (toda la red)
docker run -d -p 3000:3000 my-api:latest
# Accesible desde cualquier IP que pueda llegar al host
 
# Escenario 3: Base de datos interna
docker run -d -p 127.0.0.1:5432:5432 postgres:16
# Solo localhost (buena prΓ‘ctica para BDD)
 
# Escenario 4: Varios contenedores en mismos puertos internos
docker run -d -p 8001:80 --name web1 nginx:latest
docker run -d -p 8002:80 --name web2 nginx:latest
docker run -d -p 8003:80 --name web3 nginx:latest
# Acceder:
# http://localhost:8001  β†’ web1
# http://localhost:8002  β†’ web2
# http://localhost:8003  β†’ web3

PublicaciΓ³n en Docker Compose

# docker-compose.yml
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"                 # Todos los interfaces
      - "127.0.0.1:443:443"     # Solo localhost
 
  api:
    image: my-api:latest
    ports:
      - target: 3000            # Puerto del contenedor
        published: "8080"       # Puerto del host
        protocol: tcp           # Protocolo
        mode: host              # host = directo al host
 
  # Puertos en Swarm
  worker:
    image: my-worker:latest
    ports:
      - mode: ingress
        target: 8080
        published: "8080"

DNS en contenedores

DNS de la red bridge personalizada

En redes bridge personalizadas, Docker usa un resolver DNS integrado que resuelve:

  1. Nombres de contenedores β†’ IPs
  2. Nombres de servicios β†’ IPs
  3. Hosts del host β†’ IPs
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  DNS en red bridge personalizada                  β”‚
β”‚                                                  β”‚
β”‚  docker network create my-app-net                β”‚
β”‚                                                  β”‚
β”‚  docker run -d --name web --network my-app-net   β”‚
β”‚             nginx:latest                          β”‚
β”‚                                                  β”‚
β”‚  docker run -d --name api --network my-app-net   β”‚
β”‚             my-api:latest                        β”‚
β”‚                                                  β”‚
β”‚  docker run -d --name db --network my-app-net    β”‚
β”‚             postgres:16                          β”‚
β”‚                                                  β”‚
β”‚  DNS disponible en TODOS los contenedores:       β”‚
β”‚  - web β†’ resuelve a 172.20.0.2                   β”‚
β”‚  - api β†’ resuelve a 172.20.0.3                   β”‚
β”‚  - db  β†’ resuelve a 172.20.0.4                   β”‚
β”‚                                                  β”‚
β”‚  TambiΓ©n funciona desde dentro del contenedor:   β”‚
β”‚  curl http://api:3000                            β”‚
β”‚  psql -h db -U user                              β”‚
β”‚  wget http://web:80                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

DNS configuration

# Configurar DNS personalizado para contenedores
docker run -d --dns 8.8.8.8 --dns 8.8.4.4 nginx:latest
 
# Usar DNS del host
docker run -d --dns=host nginx:latest
 
# ConfiguraciΓ³n global en /etc/docker/daemon.json:
{
  "dns": ["8.8.8.8", "8.8.4.4"],
  "dns-search": ["mycompany.local"],
  "dns-opt": ["ndots:2"]
}

DNS interno y resoluciΓ³n

DNS resolution flow:

Contenedor quiere resolver "db"
  β”‚
  β–Ό
1. /etc/resolv.conf del contenedor
   nameserver 127.0.0.11  ← DNS interno de Docker
   search docker          ← Search domain

  β”‚
  β–Ό
2. DNS interno de Docker (127.0.0.11)
   β”‚
   β”œβ”€β”€ Si "db" es nombre de contenedor β†’ resuelve IP
   β”œβ”€β”€ Si "db" es nombre de servicio en compose β†’ resuelve IP
   β”œβ”€β”€ Si "google.com" β†’ proxy a DNS configurado
   └── Si no encuentra β†’ proxy a DNS configurado
   β”‚
   β–Ό
3. DNS externo configurado (8.8.8.8, etc.)
   β”‚
   β–Ό
4. Resultado devuelto al contenedor
# Ver el DNS interno de Docker
docker run --rm alpine:3.19 cat /etc/resolv.conf
# nameserver 127.0.0.11
# options ndots:2
 
# Ver DNS en un contenedor con red personalizada
docker run --rm --network my-app-net alpine:3.19 cat /etc/resolv.conf
# nameserver 127.0.0.11
# options ndots:2
 
# Test DNS
docker run --rm --network my-app-net alpine:3.19 nslookup db
# Server:  127.0.0.11
# Address: 127.0.0.11:53
#
# Non-authoritative answer:
# db.my-app-net.default.svc.cluster.local
# Name:      db
# Address: 172.20.0.4

Networking entre contenedores

PatrΓ³n: API + Base de datos

# Crear red dedicada
docker network create app-net
 
# Base de datos en la red
docker run -d \
  --name postgres \
  --network app-net \
  -e POSTGRES_PASSWORD=secret \
  postgres:16
 
# API conectada a la misma red
# La API accede a postgres con el nombre "postgres"
docker run -d \
  --name api \
  --network app-net \
  -p 3000:3000 \
  -e DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb \
  my-api:latest
Arquitectura de red:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  app-net (bridge personalizado)               β”‚
β”‚                                              β”‚
β”‚  api (172.22.0.2)                              β”‚
β”‚    β”œβ”€β”€ Puerto: 3000 (mapeado a host:3000)     β”‚
β”‚    └── DB_URL: postgresql://postgres:5432     β”‚
β”‚         ↑                                    β”‚
β”‚         β”‚ HTTP                               β”‚
β”‚         β”‚ TCP                                β”‚
β”‚         β–Ό                                    β”‚
β”‚  postgres (172.22.0.3)                         β”‚
β”‚    β”œβ”€β”€ Puerto: 5432 (NO mapeado al host)      β”‚
β”‚    └── Solo accesible desde app-net           β”‚
β”‚                                              β”‚
β”‚  ⚠️ postgres NO es accesible desde fuera      β”‚
β”‚     de la red app-net (bueno para seguridad)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

PatrΓ³n: Reverse proxy con Nginx

# Red frontend (accesible desde fuera)
docker network create proxy-net
 
# Nginx (expone al mundo)
docker run -d \
  --name nginx \
  --network proxy-net \
  -p 80:80 \
  -p 443:443 \
  -v ./nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx:latest
 
# API services (solo accesibles desde proxy-net)
docker network create app-net
docker network connect proxy-net api-1
docker network connect proxy-net api-2
docker network connect proxy-net api-3
 
# api-1, api-2, api-3 accesibles desde nginx con nombre
# nginx.conf:
# upstream api {
#   server api-1:3000;
#   server api-2:3000;
#   server api-3:3000;
# }
# ./nginx.conf
upstream api_backend {
    server api-1:3000;
    server api-2:3000;
    server api-3:3000;
}
 
upstream websocket {
    server websocket-1:8080;
}
 
server {
    listen 80;
    server_name example.com;
 
    location /api/ {
        proxy_pass http://api_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
 
    location /ws/ {
        proxy_pass http://websocket;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
 
    location / {
        proxy_pass http://api_backend;
    }
}

PatrΓ³n: Servicio con red interna y externa

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Multi-tier networking                      β”‚
β”‚                                             β”‚
β”‚  external-net                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Nginx   β”‚    β”‚                    β”‚    β”‚
β”‚  β”‚  :80,443 β”‚    β”‚  app-net           β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚    β”‚
β”‚      β”‚           β”‚  β”‚  api-1     β”‚    β”‚    β”‚
β”‚      β”‚           β”‚  β”‚  api-2     β”‚    β”‚    β”‚
β”‚      β”‚           β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚    β”‚
β”‚      β”‚  HTTP β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚    β”‚
β”‚      β”‚  HTTPSβ”‚    β”‚  β”‚  db        β”‚    β”‚    β”‚
β”‚      β–Ό       β”‚    β”‚  β”‚  :5432     β”‚    β”‚    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚    β”‚
β”‚  β”‚  API     β”‚β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚    β”‚
β”‚  β”‚  :3000   β”‚β”‚    β”‚  β”‚  cache     β”‚    β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚    β”‚  β”‚  :6379     β”‚    β”‚    β”‚
β”‚      β”‚       β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚    β”‚
β”‚      β”‚       β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚    β”‚
β”‚      β”‚       β”‚    β”‚  β”‚  worker    β”‚    β”‚    β”‚
β”‚      β–Ό       β”‚    β”‚  β”‚  (solo     β”‚    β”‚    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚    β”‚  β”‚   interno) β”‚    β”‚    β”‚
β”‚  β”‚  Worker  β”‚β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚    β”‚
β”‚  β”‚  (sin    β”‚    β”‚                    β”‚    β”‚
β”‚  β”‚  puertos)β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β”‚
β”‚                                             β”‚
β”‚  external-net: solo nginx (accesible fuera) β”‚
β”‚  app-net: todos los servicios              β”‚
β”‚                                             β”‚
β”‚  worker no tiene puertos expuestos           β”‚
β”‚  db y cache no tienen puertos expuestos      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Troubleshooting de red

Herramientas de diagnΓ³stico

# 1. Ver contenedores conectados a una red
docker network inspect myapp-net
 
# 2. Ver la configuraciΓ³n de red de un contenedor
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container
 
# 3. Entrar al contenedor y hacer ping
docker exec -it my-container ping -c 3 other-container
docker exec -it my-container nslookup other-container
docker exec -it my-container cat /etc/resolv.conf
 
# 4. Ver reglas de iptables
sudo iptables -t nat -L -n -v
sudo iptables -t nat -L DOCKER -n -v
 
# 5. Ver estadΓ­sticas de red del contenedor
docker stats my-container
# NET I/O muestra bytes transmitidos/recibidos
 
# 6. Ver conexiones activas
docker exec -it my-container netstat -tlnp
docker exec -it my-container ss -tlnp
docker exec -it my-container curl -I http://other-container:3000/health
 
# 7. Ver logs de red del daemon
sudo journalctl -u docker.service --since "10 min ago" | grep -i network

Problemas comunes

Problema Causa SoluciΓ³n
name or service not known DNS no resuelve Verificar que los contenedores estΓ‘n en la misma red
connection refused Servicio no estΓ‘ corriendo docker ps, verificar health check
connection timed out Puerto no mapeado / firewall Verificar -p, verificar firewall del host
Puertos internos colisionan MΓΊltiples contenedores en mismo puerto Usar -p host1:cont:80 -p host2:cont:80
Contenedor no puede acceder a internet DNS no configurado --dns 8.8.8.8 o --network host
No se accede desde otro host Puerto mapeado a 127.0.0.1 Usar 0.0.0.0:puerto o solo puerto
Red no creada antes del contenedor Network no existe Crear red antes o usar --network
Contenedores en redes diferentes no se comunican Redes no compartidas Conectar contenedor a ambas redes

Debug: conectar contenedor a red existente

# Un contenedor en ejecuciΓ³n en una red diferente
docker network connect myapp-net my-running-container
 
# Ahora puede comunicarse con otros contenedores en myapp-net
docker exec my-running-container ping other-container
 
# Desconectar
docker network disconnect myapp-net my-running-container

Networking en producciΓ³n

Seguridad de red

# 1. No exponer bases de datos al host
docker run -d --name db \
  --network backend-net \
  -e POSTGRES_PASSWORD=secret \
  postgres:16
# Sin -p β†’ solo accesible desde backend-net
 
# 2. Red interna para servicios sensibles
docker network create --internal backend-net
# --internal: sin acceso a internet, sin acceso al host
 
# 3. Proxy reverso para toda la entrada
# Solo nginx/proxy expone puertos al host
# Todos los demΓ‘s servicios en red interna
 
# 4. Limitar acceso por IP (si es necesario)
docker run -d -p 127.0.0.1:8080:80 my-api:latest
# Solo accesible desde localhost

Performance de red

# Para mΓ‘xima performance, evitar NAT:
# 1. Usar --network host (si no hay colisiΓ³n de puertos)
docker run -d --network host nginx:latest
 
# 2. Usar IPv6 directo (evita NAT)
# Configurar IPv6 en daemon.json:
{
  "ip6tables": true,
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}
 
# 3. Usar macvlan para IP dedicada
docker network create \
  --driver macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  macvlan-net
 
docker run -d --network macvlan-net --ip 192.168.1.100 nginx:latest
# El contenedor tiene su IP propia en la red fΓ­sica
# MΓ‘xima performance, sin NAT

Resumen

  • Red bridge por defecto: aislamiento de red, DNS por IP (no nombre)
  • Red bridge personalizada: DNS automΓ‘tico por nombre, recomendada para compose
  • Red host: sin aislamiento, mΓ‘xima performance, sin NAT
  • Red overlay: para clusters Swarm/Kubernetes, comunicaciΓ³n inter-host
  • Red none: sin red, para contenedores offline
  • Port mapping: -p host:container con opciones de IP y protocolo
  • DNS: resuelve nombres de contenedores y servicios automΓ‘ticamente en redes personalizadas
  • MΓΊltiples redes: un contenedor puede estar en varias redes simultΓ‘neamente
  • Seguridad: no exponer puertos de BDD, usar redes internas para servicios sensibles
  • Debug: docker network inspect, docker exec + nslookup, iptables

[!quote] La clave La regla de oro de Docker networking es: cada contenedor vive en su propia red aislada, y se comunica a travΓ©s de pasarelas controladas. Usa redes bridge personalizadas para el 99% de los casos, y solo salte a redes host/macvlan cuando el rendimiento sea crΓ­tico y comprendas las implicaciones de seguridad.

ConexiΓ³n con el resto de la wiki

Concepto tocado ArtΓ­culo en profundidad
IntroducciΓ³n a Docker [[02-infra-contenedores/01-docker-intro]]
ImΓ‘genes Docker [[02-infra-contenedores/02-docker-images]]
Contenedores [[02-infra-contenedores/03-docker-containers]]
Docker Compose [[02-infra-contenedores/04-docker-compose]]
VolΓΊmenes Docker [[02-infra-contenedores/06-docker-volumes]]
Modelos OSI/TCP-IP [[01-redes-internet/015-modelo-osi-tcpip]]