Arquitectura del contenedor unificado de producción
El archivo Dockerfile de la raíz compila en 4 etapas (multi-stage build) todo el ecosistema y genera una imagen ligera sobre node:22.23-alpine + nginx + dumb-init:
- Etapa 1 (
landing-builder): compila el sitio institucional y la documentación en Astro 5 hacia/usr/share/nginx/landing. - Etapa 2 (
frontend-builder): genera el manifiesto/version.jsony compila la SPA en Angular 22 hacia/usr/share/nginx/html. - Etapa 3 (
backend-builder): genera el cliente de Prisma 7 y compila la API en NestJS 12 (Fastify 5) hacia/app/backend/dist. - Etapa 4 (
production): al arrancar,docker/entrypoint.prod.shejecuta automáticamenteprisma migrate deploy, aplica el seed idempotente de catálogos geográficos, aprovisiona el administrador inicial (si se definieron las variablesPLATFORM_ADMIN_*) y levanta NestJS en127.0.0.1:3000junto con Nginx en el puerto80.
Requisitos del servidor
- VPS o Servidor Linux: mínimo 2 vCPU y 4 GB de RAM (Ubuntu 22.04 / 24.04 LTS o Debian 12).
- Base de datos: MariaDB
11.8(juego de caracteresutf8mb4_uca1400_ai_ci). - Almacén en memoria: Redis
8.x(para límites de intentos y bloqueos temporales). - Orquestador recomendado: Dokploy o Docker Compose v2.
Variables de entorno de producción
Configura el siguiente bloque de variables en tu servicio de aplicación en Dokploy (o archivo .env de producción):
NODE_ENV=production
PORT=3000
TRUST_PROXY=1
DEFAULT_COUNTRY_ISO=CO
# Conexión a MariaDB 11.8 y Redis 8
DATABASE_URL=mysql://iglesia238:TU_CLAVE_DB@host-mariadb:3306/iglesia238
REDIS_URL=redis://default:TU_CLAVE_REDIS@host-redis:6379
# Seguridad JWT (mínimo 32 caracteres aleatorios) y dominios públicos
JWT_SECRET=genera_una_cadena_hexadecimal_segura_de_64_caracteres
APP_BASE_URL=https://app.tu-dominio.org
CORS_ORIGIN=https://app.tu-dominio.org,https://tu-dominio.org,https://www.tu-dominio.org
# Administrador inicial de plataforma (se crea de forma idempotente en el primer arranque)
PLATFORM_ADMIN_EMAIL=admin@tu-dominio.org
PLATFORM_ADMIN_PASSWORD=TuContrasenaInicialSegura2026!
PLATFORM_ADMIN_NAME=Administrador Principal
# Correo transaccional SMTP (Amazon SES recomendado)
SMTP_HOST=email-smtp.us-west-2.amazonaws.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=AKIAXXXXXXXXXXXXXXXX
SMTP_PASSWORD=TuPasswordSmtpDeIamEnAwsSes
SMTP_FROM=Iglesia 238 <no-reply@tu-dominio.org>
Si tu panel de Dokploy entrega la cadena interna con el esquema mariadb://..., el script docker/entrypoint.prod.sh la convierte automáticamente a mysql://... antes de ejecutar Prisma y NestJS.
Despliegue paso a paso en Dokploy
- Crea un proyecto en Dokploy y añade dos servicios internos: MariaDB 11.8 y Redis 8.
- Crea un servicio de tipo Application apuntando al repositorio
https://github.com/lopezsoft/iglesia238.git(ramamain, Build Type: Dockerfile, rutaDockerfile). - En la pestaña Environment, pega las variables del bloque anterior y haz clic en Save.
- En la pestaña Domains, agrega tus dominios apuntando todos al Container Port
80con HTTPS (Let's Encrypt) activo:tu-dominio.orgywww.tu-dominio.org→ sirven el sitio Astro y/docs.app.tu-dominio.org→ sirve la aplicación Angular y hace proxy de/api/*.api.tu-dominio.org→ expone directamente la API NestJS.
- Haz clic en Deploy.
Configuración de correo transaccional con AWS SES
Para que las invitaciones, la verificación de correo en el autorregistro de sedes (/register-congregation) y la recuperación de contraseñas lleguen con firma DKIM y plantillas HTML corporativas:
- En AWS Console → Amazon SES → Identities, verifica tu dominio con Easy DKIM (RSA 2048-bit) y agrega los 3 registros
CNAMEen tu DNS. - En Configuración de SMTP, elige la opción Credenciales SMTP de IAM (evita SMTP de Mail Manager para no incurrir en cargos fijos por hora de puntos de enlace) y genera el usuario SMTP.
- Copia el usuario (
AKIA...) y la contraseña SMTP en las variablesSMTP_USERySMTP_PASSWORDconSMTP_PORT=465ySMTP_SECURE=true.
Auto-actualización del Frontend y CI/CD
Cada vez que compilas una nueva versión, el script frontend/scripts/write-version-manifest.mjs sincroniza automáticamente frontend/public/version.json y environment.ts. Nginx sirve /version.json con cabeceras Cache-Control: no-store, no-cache, must-revalidate, y el servicio VersionUpdateService en Angular recarga de forma transparente las pestañas abiertas cuando detecta una versión nueva.