Saltar a contenido

Redes Docker del Ecosistema Timeliber

Cuadrante 04_EXPLANATION — qué redes existen, quién las usa, por qué. Última actualización: 2026-05-15 — Sprint Doc-3 (drift corregido contra infra/docker-compose.yml real).


1. ¿Qué es una red Docker y por qué existe?

Una red Docker es una red privada lógica dentro del servidor. Los containers en la misma red pueden hablarse por nombre. Los containers en redes diferentes están aislados — aunque corran en el mismo host.

Por qué importa: la base de datos NUNCA debe estar en la misma red que el tráfico de internet. Si un atacante accede a la capa pública, el aislamiento de redes impide alcanzar PostgreSQL.


2. Las DOS redes del ecosistema

Ambas son externas (creadas antes del primer docker compose up) para evitar colisiones de naming:

docker network create timeliber-net   # red interna
docker network create proxy-net       # red de Traefik

2.1 proxy-net — Red pública

  • Quiénes están: Traefik (corre fuera del workspace, ver §4) + servicios que necesitan exposición pública vía HTTPS (frontends de apps, APIs públicas).
  • Para qué: Traefik solo enruta HTTPS a containers que pertenezcan a esta red.
  • Analogía: la recepción del hotel — todo lo que viene de internet pasa por aquí.

2.2 timeliber-net — Red interna

  • Quiénes están: Postgres, Redis, Qdrant, n8n, Evolution, y todos los backends de apps (Travel, Gastro, AI Orchestrator, RAG).
  • Para qué: comunicación stateless entre backends y datos persistentes, sin exposición externa.
  • Analogía: la cocina del hotel — solo personal autorizado.

⚠️ Nota histórica: en versiones antiguas la red interna se llamaba timeliber-travel-backend_timeliber-network. La denominación actual canónica es timeliber-net (configurable por INFRA_NETWORK_NAME en infra/.env). Si encuentras la denominación antigua en código viejo, actualizar.


3. Tabla de servicios → redes (validada contra infra/docker-compose.yml real)

Servicios en infra/docker-compose.yml

Container (nombre real) proxy-net timeliber-net Motivo
timeliber-postgres DB aislada, jamás expuesta a internet
timeliber-redis Cache aislado
timeliber-qdrant Dashboard expuesto a HTTPS + escritura local de vectores
timeliber-n8n-prod Webhooks WhatsApp + guarda flujos en PostgreSQL
timeliber-evolution-prod Gateway WhatsApp + sesiones en evolution_db + Redis

Servicios externos (NO en infra/docker-compose.yml)

Container Ubicación Redes
Traefik ~/traefik/docker-compose.yml (fuera del workspace) proxy-net (solo)

Servicios de aplicaciones (en apps/*/)

Container proxy-net timeliber-net Motivo
travel-backend API que lee/escribe travel_db
travel-frontend Solo sirve HTML
gastro-backend API que lee/escribe gastro_db + cache Redis
gastro-admin SPA estática (Vite build → nginx en contenedor)
gastro-menu Next.js standalone
ai-orchestrator ✅ (via Traefik si público) LangGraph + checkpoints Redis + Travel HTTP
rag-studio ⚠️ pendiente compose Cliente Qdrant + LightRAG local
main-backend Solo SMTP + leads (sin BD operativa)
main-frontend Next.js SSR
omnicortex-frontend red propia omnicortex-internal Same-Origin Always (ver OmniCortex ARCHITECTURE)
omnicortex-backend red propia omnicortex-internal Nunca expuesto directo a internet

4. Traefik vive fuera del workspace

Traefik no está en infra/docker-compose.yml. La carpeta infra/traefik/ existe pero está vacía (legacy — registrado en infra/TECH_DEBT.md como INFRA-DOC3).

Ubicación real: ~/traefik/ con su propio docker-compose.yml y .env:

~/traefik/
├── docker-compose.yml       ← Servicio Traefik v2.11 (NO commiteado al monorepo)
├── .env                     ← TRAEFIK_DASHBOARD_HASH, ACME_EMAIL
├── traefik.yml              ← Config estática (entrypoints, certresolvers)
└── acme.json                ← Certificados Let's Encrypt persistentes (chmod 600)

Por qué fuera del workspace: Traefik es un servicio compartido del servidor (puede atender múltiples monorepos en el mismo host). Si se incluyera en el workspace, no podría reutilizarse para otros proyectos.

Las labels Traefik (traefik.enable=true, etc.) sí viven en cada docker-compose.yml de los servicios expuestos — eso es service discovery, no contraría que Traefik viva externo.

Detalle del flujo de una petición → traefik-proxy.md.


5. Resolución DNS interna

Dentro de una red Docker, los containers se llaman entre sí por nombre, no por IP. Docker resuelve por DNS interno; las IPs flotantes cambian al recrear contenedores.

# travel_backend se conecta a Postgres
# En su .env:
POSTGRES_HOST=timeliber-postgres   # ← nombre real del container (ver docker-compose.yml de infra)

# Docker, vía DNS interno en timeliber-net, lo resuelve automáticamente.

Regla absoluta: NUNCA hardcodear IPs en configuración. Siempre usar el nombre del container.


6. Diagnóstico rápido

# ¿En qué redes está un container?
docker inspect timeliber-postgres | jq '.[0].NetworkSettings.Networks | keys'

# ¿Un container alcanza otro por nombre?
docker exec timeliber-n8n-prod ping -c 2 timeliber-postgres

# Conectar manualmente un container a una red (sin recrearlo)
docker network connect timeliber-net <nombre_container>

# Listar containers en una red
docker network inspect timeliber-net | jq '.[0].Containers | to_entries[] | .value.Name'

# Forzar a Traefik a re-leer service discovery
docker restart traefik   # (corre en ~/traefik/, no aquí)

7. Dónde vive cada .env

~/traefik/.env                                            ← Traefik (dashboard password, ACME)
~/software/timeliber-workspace/infra/.env                 ← Infra compartida (Postgres, Redis, Qdrant, n8n, Evolution)
~/software/timeliber-workspace/apps/main/{backend,frontend}/.env
~/software/timeliber-workspace/apps/travel/{backend,frontend}/.env
~/software/timeliber-workspace/apps/gastro/{backend,frontend}/.env
~/software/timeliber-workspace/apps/ai-orchestrator/.env
~/software/timeliber-workspace/apps/tools/rag/.env
~/software/timeliber-workspace/apps/visionArtificial/OmniCortex/.env.local

Regla absoluta: ningún .env real va a Git. Todos están en .gitignore. Si por error subes credenciales reales → rotar TODAS las contraseñas inmediatamente y de manera transversal.


8. Lección aprendida (2026-03-31) — vigente

Incidente: evolution-api y n8n arrancaron solo en proxy-net. No podían escribir a timeliber-postgres ni a timeliber-redis porque éstos viven en timeliber-net.

Síntoma operativo: webhooks de WhatsApp llegaban (Evolution responde HTTP), pero las sesiones no se persistían y los flujos de n8n fallaban silenciosamente al guardar.

Solución aplicada: ambos servicios fueron añadidos a las dos redes:

services:
  n8n:
    networks: [timeliber-net, proxy-net]   # ← AMBAS
  evolution-api:
    networks: [timeliber-net, proxy-net]   # ← AMBAS

Esta corrección ya está fijada permanentemente en infra/docker-compose.yml desde abril 2026.

Costo del incidente: 2 horas de downtime productivo. Regla derivada:

Cualquier servicio que reciba webhooks o tráfico HTTP de internet Y necesite persistencia, debe estar en proxy-net + timeliber-net. Validar antes del deploy.


9. Referencias


Drift corregido vs infra/docker-compose.yml real en Sprint Doc-3 (2026-05-15). Si encuentras drift nuevo → registrar en TECH_DEBT.md.