Cada contenedor obtiene su propio namespace de red: interfaces, direcciones, rutas, puertos y tabla de conexiones. Docker conecta esos namespaces mediante networks y drivers, y ofrece service discovery en redes definidas por el usuario.
Texto
container api namespace
├── loopback
├── eth0
├── rutas
└── sockets
↓ veth / driver
Docker network
↓
host y otros containers
La consecuencia más importante es que localhost, una IP y un puerto siempre deben interpretarse desde el namespace donde se ejecuta el proceso.
Dentro del contenedor, el proceso ve una red aislada:
su propia interfaz loopback;
interfaces virtuales;
rutas;
DNS configurado;
puertos escuchando;
conexiones activas.
Dos containers pueden escuchar ambos en 0.0.0.0:3000 sin conflicto porque están en namespaces diferentes. El conflicto aparece al publicar ambos en el mismo puerto del host.
Para otro container usa su nombre DNS. Para el host usa un mecanismo explícito soportado por la plataforma. Para un sistema externo usa su hostname o IP enrutable.
Una network limita qué endpoints son directamente alcanzables, pero no reemplaza:
passwords;
TLS;
autorización;
validación de inputs;
firewall del host;
políticas del servicio.
Un proceso comprometido dentro de api puede usar todas las conexiones permitidas a api. Aplica mínimo acceso también a credenciales y roles de database.
En Linux, macOS y Windows el mecanismo puede diferir. Docker Desktop suele ofrecer un nombre especial para el host. En Engine nativo pueden usarse gateways o mappings explícitos.
No hardcodees una IP descubierta manualmente. Documenta la dependencia y prueba en cada plataforma.
Una arquitectura mejor suele evitar que un container dependa de un proceso local no gestionado cuando se despliega fuera del equipo del desarrollador.
VPNs y overlays pueden causar paquetes fragmentados o conexiones que fallan solo con payloads grandes. Revisa MTU cuando pequeños requests funcionan y grandes no.