# RUNBOOK — stack local dockerizado (fase 3, validación) Stack Docker Compose del sistema modernizado de "Todos contra el fuego": web Meteor 3.1 (Node 22), MongoDB 7 (replica set de un nodo), Redis (AOF), `tcef-notifications` y node-red. **Es el entorno de validación local previo a producción** — el despliegue real irá al ansible de Comunes (fase 3 del plan); este compose no toca el proxy ni la infra compartida. ## Requisitos - Docker + Docker Compose v2. - El repo hermano `../tcef-notifications` (el compose construye su imagen desde ahí). ## Primer arranque ```bash # 1. Secretos (gitignorados; ver secrets/README.md) cp settings-development.json secrets/meteor-settings.json cp secrets/notifications.env.example secrets/notifications.env # MODE=dry-run # 2. Construir y levantar (el primer build de la web tarda: descarga meteor-tool # y compila el bundle; ~10-20 min en frío) docker compose build docker compose up -d # 3. Comprobar salud docker compose ps # todo "healthy" / mongo-init "exited (0)" ``` Servicios y puertos en el host: | Servicio | Contenedor | URL / puerto | |---|---|---| | web Meteor | `tcef-stack-web` | http://localhost:3200 | | node-red | `tcef-stack-node-red` | http://localhost:1880 | | MongoDB 7 | `tcef-stack-mongo` | solo red interna (usar `docker exec`) | | Redis | `tcef-stack-redis` | solo red interna | | notificaciones | `tcef-stack-notifications` | sin puerto (worker) | `mongo-init` es un one-shot: inicia el replica set `rs0` y fija `db.migrations` a la versión 18 (los `up()` históricos ya son async, pero se pinta v18 porque los datos reales de producción llegan pre-migrados). > Nota healthcheck: los checks usan `127.0.0.1`, no `localhost`. El `wget` de > busybox (alpine) resuelve `localhost` a `::1` (IPv6) primero, pero los > servidores Meteor/node-red escuchan solo en IPv4 → un `localhost` daría > unhealthy aunque la app responda perfectamente por el puerto mapeado. ## Smoke test REST (red de seguridad del contrato Flutter) Debe ser **byte-idéntico** a los snapshots committeados: ```bash MONGO_CONTAINER=tcef-stack-mongo MONGO_SHELL=mongosh MONGO_PORT=27017 \ BASE_URL=http://localhost:3200 ./smoke/smoke.sh ``` ## Operación diaria ```bash docker compose logs -f web # logs de un servicio (rotados: 3×10MB) docker compose ps # estado + healthchecks docker compose restart notifications # reiniciar un servicio docker compose down # parar todo (los volúmenes persisten) docker compose down -v # ⚠️ borra también mongo/redis/node-red ``` ## Desplegar una nueva versión ```bash # web (tras cambios en el repo) docker compose build web && docker compose up -d web # notificaciones (tras cambios en ../tcef-notifications) docker compose build notifications && docker compose up -d notifications ``` Verificar tras cada despliegue de la web: `docker compose ps` healthy + smoke REST byte-idéntico (arriba). ## Backups y restauración (volúmenes locales) ```bash # Mongo: dump / restore de la db fuegos docker exec tcef-stack-mongo mongodump --db fuegos --archive > fuegos.dump docker exec -i tcef-stack-mongo mongorestore --archive --drop < fuegos.dump # node-red: tar del volumen de datos docker run --rm -v tcef-stack_nodered-data:/data -v "$PWD:/backup" alpine \ tar czf /backup/nodered-data.tgz -C /data . ``` ## Rollback - **web**: `git checkout ` + `docker compose build web && docker compose up -d web`. (En producción se conservará la imagen anterior etiquetada; aquí basta git.) - **notificaciones**: igual, desde `../tcef-notifications`. `KILL_SWITCH=1` en `secrets/notifications.env` + `docker compose up -d notifications` detiene todo envío al instante sin parar el servicio. - **datos**: restaurar el último dump (arriba). ## Salvaguardas de notificaciones `secrets/notifications.env` arranca en `MODE=dry-run` (no envía nada). La progresión dry-run → shadow → canary → full está documentada en `../tcef-notifications/docs/rollout.md` y **nunca** se salta pasos. En este stack local no hay credenciales reales salvo que las pongas tú. ## Deuda conocida de este compose - `tcef-notifications` no expone endpoint HTTP de salud → healthcheck por proceso (`pgrep`). Añadir `/healthz` al servicio cuando toque. - node-red corre la imagen oficial vacía (los flows de los bots viven en shiva; su migración de datos es parte del cutover real de fase 3). - El driver mongodb 3.7 de `tcef-notifications` (elegido por el Mongo 3.2 de producción) conecta con Mongo 7 en pruebas locales, pero al hacer el cutover real a Mongo 7 debe subirse a driver 6.x (y habilitar change streams).