Despliegue con Caddy y Docker
Este documento describe el despliegue de UnoSportClub con Docker y, opcionalmente, Caddy como proxy con terminación TLS.
El repositorio unosport-v0.4 (monorepo) expone una imagen unificada (raíz, Dockerfile): un solo contenedor con Nginx en el puerto 80 y Node.js (API) en el 5000 solo hacia dentro; Nginx enruta por nombre de host (Host), no por puertos distintos por aplicación. Más abajo, el apéndice Legado pre-v0.4 documenta despliegues anteriores (Firebase, multi-imagen).
Imagen unificada del monorepo
Arquitectura interna
-
Construcción:
npm run build:production:ally build de Antora/docs; los artefactos quedan bajo/srv/static/…dentro de la imagen. -
Nginx (
EXPOSE 80): sirve cada SPA segúnserver_namey proxifica hacia Node las rutas/api,/oauth/,/.well-knowny/socket.io. -
Node (
PORT/FUNCTIONS_PORT, por defecto 5000): no debe publicarse al host; el tráfico de API llega vía Nginx en 80. -
Plantilla:
docker/nginx.conf.templatesustituida en arranque pordocker/docker-entrypoint.shconenvsubst(UNOSPORT_HOST_*,FUNCTIONS_PORT).
Variables de host obligatorias
Los FQDN deben coincidir con lo que resuelve DNS (o /etc/hosts) y con el proxy delante:
-
UNOSPORT_HOST_APP— aplicación principal (usuarios) -
UNOSPORT_HOST_PANEL— panel operador -
UNOSPORT_HOST_TRAINER— panel entrenador -
UNOSPORT_HOST_SUDO— panel super usuario -
UNOSPORT_HOST_ACCOUNTING— contabilidad -
UNOSPORT_HOST_DOCS— sitio de documentación estática
Valores por defecto en el entrypoint: *.unosport.local (solo desarrollo local).
Variables de aplicación y secretos
Reutiliza las mismas variables que el backend en functions/ (ver functions/.env.example): PostgreSQL (DB_*, DB_NAME_ACCOUNTING, DB_SSL), OAuth2 (OAUTH2_ISSUER_BASE_URL, OAUTH2_AUDIENCE, OAUTH2_CLIENT_ID, OAUTH2_CLIENT_SECRET, SALT_SEPARATOR, SIGNER_KEY), BOT_API_KEYS, PUSHER_*, SMTP, etc.
Con HTTPS delante, OAUTH2_ISSUER_BASE_URL debe ser la URL pública del issuer (p. ej. https://app.ejemplo.com/), alineada con el frontend y el proxy.
Ejemplo docker-compose (un servicio de aplicación)
Sustituye la imagen por el tag que publique CI (p. ej. GHCR). PostgreSQL puede seguir siendo un servicio aparte.
services:
unosport-qa:
image: ghcr.io/cortex-ia-com-co/unosportclub:staging
pull_policy: always
restart: unless-stopped
ports:
- "8080:80"
environment:
PORT: "5000"
FUNCTIONS_PORT: "5000"
NODE_ENV: staging
UNOSPORT_HOST_APP: app.qa.ejemplo.com
UNOSPORT_HOST_PANEL: panel.qa.ejemplo.com
UNOSPORT_HOST_TRAINER: entrenador.qa.ejemplo.com
UNOSPORT_HOST_SUDO: control.qa.ejemplo.com
UNOSPORT_HOST_ACCOUNTING: accounting.qa.ejemplo.com
UNOSPORT_HOST_DOCS: docs.qa.ejemplo.com
DB_HOST: unosport-db-qa
DB_PORT: "5432"
DB_NAME: ${DB_NAME_QA:-unosportclub_qa}
DB_USER: ${DB_USER_QA:-unosport_admin}
DB_PASSWORD: ${DB_PASSWORD_QA}
DB_NAME_ACCOUNTING: ${QA_DB_NAME_ACCOUNTING}
DB_SSL: "false"
OAUTH2_ISSUER_BASE_URL: ${OAUTH2_PUBLIC_ISSUER}
OAUTH2_AUDIENCE: ${OAUTH2_AUDIENCE}
OAUTH2_CLIENT_ID: ${OAUTH2_CLIENT_ID}
OAUTH2_CLIENT_SECRET: ${OAUTH2_CLIENT_SECRET}
SALT_SEPARATOR: ${SALT_SEPARATOR}
SIGNER_KEY: ${SIGNER_KEY}
BOT_API_KEYS: ${BOT_API_KEYS}
depends_on:
unosport-db-qa:
condition: service_healthy
networks:
- n8n_frontend
healthcheck:
test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1/api"]
interval: 15s
timeout: 5s
retries: 3
start_period: 60s
Notas:
-
Si la imagen no incluye
wget, instálalo en elDockerfileo usacurlequivalente entest. -
user: 10000:10000: el entrypoint oficial ejecuta Nginx; comprobad compatibilidad con permisos de/var/lib/nginxantes de forzar usuario no root. -
El entrypoint de la imagen unificada no ejecuta
node db/install.js; las migraciones deben lanzarse condocker compose execo un job de despliegue (ver Migraciones con la imagen unificada).
Migraciones con la imagen unificada
docker compose exec unosport-qa sh -c "cd /app/functions && node db/install.js"
Ejecutad esto tras el primer despliegue o cuando haya migraciones nuevas, con la base de datos accesible desde las variables DB_*.
Caddy delante de la imagen unificada
Un solo upstream al puerto 80 del servicio; Caddy reenvía el header Host y Nginx interno elige la SPA. No hace falta enrutar /api a otro contenedor.
app.qa.ejemplo.com,
panel.qa.ejemplo.com,
trainer.qa.ejemplo.com,
sudo.qa.ejemplo.com,
accounting.qa.ejemplo.com,
docs.qa.ejemplo.com {
encode zstd gzip
request_body {
max_size 10MB
}
reverse_proxy unosport-qa:80
}
Si Caddy corre en el host y el contenedor publica 8080:80, usad 127.0.0.1:8080 en lugar de unosport-qa:80.
Arquitectura de Despliegue
Componentes del Sistema
Modelo unificado (actual en monorepo)
-
Contenedor único: Nginx + API Node + todos los builds Angular y docs estáticos
-
Caddy (opcional): TLS y proxy reverso hacia el puerto publicado 80 del contenedor
-
PostgreSQL: base de datos (contenedor dedicado o gestionada)
Modelo legado (varias imágenes)
Si aún usáis imágenes separadas por repositorio o tag:
-
Backend (Functions): API REST en Node.js/Express
-
Frontend: aplicaciones Angular en imágenes distintas (
unosportclub,panel,trainer,sudo,accounting, …) -
Caddy: reverse proxy hacia cada servicio
-
PostgreSQL: relacional (Staging/QA o Cloud SQL en producción)
Entornos de Despliegue
El sistema soporta tres entornos independientes:
-
Production: Ambiente de producción con datos reales
-
Staging: Ambiente de pruebas previo a producción
-
QA: Ambiente de control de calidad y testing
Cada entorno tiene: * Sus propios contenedores Docker * Su propia base de datos PostgreSQL (Staging y QA) * Sus propios subdominios * Configuraciones independientes
Configuración de Docker Compose (modelo legado)
El siguiente ejemplo asume varias imágenes (API + un contenedor por frontend). Para nuevos despliegues desde el monorepo, preferid la imagen unificada.
Estructura del docker-compose.yml
El archivo docker-compose.yml define todos los servicios necesarios en el modelo multi-contenedor:
version: '3.8'
services:
# Production Backend
unosport-backend:
image: ghcr.io/cortex-ia-com-co/unosportclub-functions:latest
pull_policy: always
restart: unless-stopped
user: 10000:10000
volumes:
- ./unosportclub/firebase/firebase-adminsdk.json:/firebase-adminsdk.json:ro
- ./unosportclub/.env:/app/.env:ro
networks:
- n8n_frontend
# Production Frontend Applications
unosport-app:
image: ghcr.io/cortex-ia-com-co/unosportclub:v0.0.1-p1
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
unosport-panel:
image: ghcr.io/cortex-ia-com-co/unosportclub-panel:v0.1.8
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
unosport-trainer:
image: ghcr.io/cortex-ia-com-co/unosportclub-trainer:latest
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
unosport-sudo:
image: ghcr.io/cortex-ia-com-co/unosportclub-sudo:latest
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
# Staging Environment
unosport-db-staging:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME:-unosportclub_staging}
POSTGRES_USER: ${DB_USER:-unosport_admin}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- unosport_db_staging:/var/lib/postgresql/data
networks:
- n8n_frontend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-unosport_admin}"]
interval: 10s
timeout: 5s
retries: 5
unosport-backend-staging:
image: ghcr.io/cortex-ia-com-co/unosportclub-functions:staging
pull_policy: always
restart: unless-stopped
user: 10000:10000
depends_on:
unosport-db-staging:
condition: service_healthy
environment:
NODE_ENV: staging
DATABASE_URL: postgresql://${DB_USER:-unosport_admin}:${DB_PASSWORD}@unosport-db-staging:5432/${DB_NAME:-unosportclub_staging}
DB_HOST: unosport-db-staging
DB_PORT: 5432
DB_NAME: ${DB_NAME:-unosportclub_staging}
DB_USER: ${DB_USER:-unosport_admin}
DB_PASSWORD: ${DB_PASSWORD}
DB_SSL: "false"
GOOGLE_APPLICATION_CREDENTIALS: /firebase-adminsdk.json
FIREBASE_PROJECT_ID: unosportclubdev
FIREBASE_REGION: us-central1
volumes:
- ./unosportclub/firebase/firebase-adminsdk.json:/firebase-adminsdk.json:ro
command: >
sh -c "
cd /app &&
node db/install.js &&
node server_wrapper.js
"
networks:
- n8n_frontend
unosport-app-staging:
image: ghcr.io/cortex-ia-com-co/unosportclub:staging
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
unosport-panel-staging:
image: ghcr.io/cortex-ia-com-co/unosportclub-panel:staging
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
unosport-trainer-staging:
image: ghcr.io/cortex-ia-com-co/unosportclub-trainer:staging
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
unosport-sudo-staging:
image: ghcr.io/cortex-ia-com-co/unosportclub-sudo:staging
pull_policy: always
restart: unless-stopped
networks:
- n8n_frontend
# QA Environment
unosport-db-qa:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME_QA:-unosportclub_qa}
POSTGRES_USER: ${DB_USER_QA:-unosport_admin}
POSTGRES_PASSWORD: ${DB_PASSWORD_QA:-${DB_PASSWORD}}
volumes:
- unosport_db_qa:/var/lib/postgresql/data
networks:
- n8n_frontend
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER_QA:-unosport_admin}"]
interval: 10s
timeout: 5s
retries: 5
unosport-qa:
image: ghcr.io/cortex-ia-com-co/unosportclub:staging
pull_policy: always
restart: unless-stopped
depends_on:
unosport-db-qa:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "-O-", "http://127.0.0.1/api"]
interval: 15s
timeout: 5s
retries: 3
start_period: 60s
environment:
PORT: "5000"
FUNCTIONS_PORT: "5000"
NODE_ENV: staging
UNOSPORT_HOST_APP: app.qa.unosportclub.com.co
UNOSPORT_HOST_PANEL: panel.qa.unosportclub.com.co
UNOSPORT_HOST_TRAINER: entrenador.qa.unosportclub.com.co
UNOSPORT_HOST_SUDO: control.qa.unosportclub.com.co
UNOSPORT_HOST_ACCOUNTING: accounting.qa.unosportclub.com.co
UNOSPORT_HOST_DOCS: docs.qa.unosportclub.com.co
DB_HOST: unosport-db-qa
DB_PORT: "5432"
DB_NAME: ${DB_NAME_QA:-unosportclub_qa}
DB_USER: ${DB_USER_QA:-unosport_admin}
DB_PASSWORD: ${DB_PASSWORD_QA:-${DB_PASSWORD}}
DB_SSL: "false"
OAUTH2_ISSUER_BASE_URL: ${OAUTH2_PUBLIC_ISSUER}
networks:
- n8n_frontend
# Caddy Reverse Proxy
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
user: 10000:10000
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy_data:/data
- ./caddy_config:/config
networks:
- n8n_frontend
networks:
n8n_frontend:
volumes:
unosport_db_staging:
driver: local
unosport_db_qa:
driver: local
Características Importantes
Health Checks
Los servicios de base de datos incluyen health checks para asegurar que estén listos antes de iniciar los servicios dependientes:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-unosport_admin}"]
interval: 10s
timeout: 5s
retries: 5
Configuración de Caddy
Imagen unificada: un upstream por entorno
Con el contenedor descrito en Imagen unificada del monorepo, todas las aplicaciones comparten el mismo puerto 80 dentro del contenedor; el proxy solo debe preservar el header Host. Ejemplo (QA):
app.qa.unosportclub.com.co,
panel.qa.unosportclub.com.co,
entrenador.qa.unosportclub.com.co,
control.qa.unosportclub.com.co,
accounting.qa.unosportclub.com.co,
docs.qa.unosportclub.com.co {
encode zstd gzip
request_body {
max_size 10MB
}
reverse_proxy unosport-qa:80
}
Los nombres deben coincidir con UNOSPORT_HOST_* del contenedor.
Estructura del Caddyfile (modelo legado)
El archivo Caddyfile define el enrutamiento cuando API y frontends son servicios Docker separados (enrutar /api* al backend y el resto a cada frontend):
# Production Environment
app.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend:3000
reverse_proxy unosport-app:80
}
entrenador.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend:3000
reverse_proxy unosport-trainer:80
}
panel.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend:3000
reverse_proxy unosport-panel:80
}
control.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend:3000
reverse_proxy unosport-sudo:80
}
# Staging Environment
app.staging.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend-staging:3000
reverse_proxy unosport-app-staging:80
}
entrenador.staging.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend-staging:3000
reverse_proxy unosport-trainer-staging:80
}
panel.staging.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend-staging:3000
reverse_proxy unosport-panel-staging:80
}
control.staging.unosportclub.com.co {
encode zstd gzip
reverse_proxy /api* unosport-backend-staging:3000
reverse_proxy unosport-sudo-staging:80
}
# QA Environment (en el repositorio: imagen unificada; un bloque por host, mismo upstream)
app.qa.unosportclub.com.co {
encode zstd gzip
request_body {
max_size 10MB
}
reverse_proxy unosport-qa:80
}
entrenador.qa.unosportclub.com.co {
encode zstd gzip
request_body {
max_size 10MB
}
reverse_proxy unosport-qa:80
}
# panel, control, accounting, docs: mismo patrón hacia unosport-qa:80
Variables de Entorno
Archivo .env
El archivo .env en /opt/n8n/unosportclub/.env contiene la configuración de producción:
# Configuración de Base de Datos - Functions
DATABASE_URL="postgresql://unosportclub:GtTFWfP39IA643IrV1GxWJ5DVJAmBIif@pegasus.cortex-ia.com.co/unosportclub"
GOOGLE_APPLICATION_CREDENTIALS=/firebase-adminsdk.json
PORT=3000
HOST=0.0.0.0
Variables para Staging y QA
Las variables de entorno para Staging y QA se definen directamente en docker-compose.yml:
environment:
NODE_ENV: staging
DATABASE_URL: postgresql://${DB_USER:-unosport_admin}:${DB_PASSWORD}@unosport-db-staging:5432/${DB_NAME:-unosportclub_staging}
DB_HOST: unosport-db-staging
DB_PORT: 5432
DB_NAME: ${DB_NAME:-unosportclub_staging}
DB_USER: ${DB_USER:-unosport_admin}
DB_PASSWORD: ${DB_PASSWORD}
DB_SSL: "false"
GOOGLE_APPLICATION_CREDENTIALS: /firebase-adminsdk.json
FIREBASE_PROJECT_ID: unosportclubdev
FIREBASE_REGION: us-central1
Proceso de Despliegue
Despliegue Inicial
-
Clonar configuración de despliegue:
cd /opt/n8n git clone <repository-url> cd unosportclub -
Configurar variables de entorno:
cp .env.example .env # Editar .env con credenciales reales -
Configurar credenciales de Firebase:
# Colocar firebase-adminsdk.json en ./unosportclub/firebase/ -
Iniciar servicios:
docker-compose up -d
Actualización de Servicios
Para actualizar un servicio específico:
# Actualizar backend de producción
docker-compose pull unosport-backend
docker-compose up -d unosport-backend
# Actualizar aplicación frontend
docker-compose pull unosport-app
docker-compose up -d unosport-app
# Actualizar todos los servicios de un entorno
docker-compose pull unosport-backend-staging unosport-app-staging unosport-panel-staging unosport-trainer-staging unosport-sudo-staging
docker-compose up -d unosport-backend-staging unosport-app-staging unosport-panel-staging unosport-trainer-staging unosport-sudo-staging
Reinicio de Servicios
# Reiniciar un servicio específico
docker-compose restart unosport-backend
# Reiniciar todos los servicios de un entorno
docker-compose restart unosport-backend-staging unosport-app-staging unosport-panel-staging unosport-trainer-staging unosport-sudo-staging
# Reiniciar todos los servicios
docker-compose restart
Gestión de Base de Datos
Migraciones Automáticas
Los servicios de backend ejecutan automáticamente las migraciones al iniciar mediante el comando:
node db/install.js
Este script: * Verifica la conexión a la base de datos * Ejecuta migraciones pendientes * Carga seeders si es necesario
Migración Inicial Manual dentro del Contenedor
En algunos casos, puede ser necesario ejecutar las migraciones manualmente dentro del contenedor, especialmente cuando:
-
Las migraciones automáticas fallaron durante el inicio
-
Necesitas ejecutar migraciones en un contenedor ya corriendo
-
Quieres verificar el estado de las migraciones antes de iniciar el servidor
-
Necesitas ejecutar migraciones sin reiniciar el servicio
Ejecutar Migraciones en Contenedor Corriendo
Para ejecutar migraciones en un contenedor que ya está corriendo:
# Staging - Ejecutar migraciones dentro del contenedor
docker-compose exec unosport-backend-staging sh -c "cd /app && node db/install.js"
# QA (imagen unificada) — código en /app/functions
docker-compose exec unosport-qa sh -c "cd /app/functions && node db/install.js"
Verificar Estado de Migraciones
Para verificar qué migraciones se han ejecutado:
# Conectarse al contenedor de backend
docker-compose exec unosport-backend-staging sh
# Dentro del contenedor, ejecutar:
cd /app
node -e "const {pool} = require('./db/index'); pool.query('SELECT * FROM schema_migrations ORDER BY id').then(r => {console.table(r.rows); pool.end();})"
O usando psql directamente en el contenedor de base de datos:
# Ver migraciones ejecutadas en Staging
docker-compose exec unosport-db-staging psql -U unosport_admin -d unosportclub_staging -c "SELECT * FROM schema_migrations ORDER BY id;"
# Ver migraciones ejecutadas en QA
docker-compose exec unosport-db-qa psql -U unosport_admin -d unosportclub_qa -c "SELECT * FROM schema_migrations ORDER BY id;"
Ejecutar Migraciones sin Seeders
Si necesitas ejecutar solo las migraciones sin los seeders:
# Staging - Solo migraciones
docker-compose exec unosport-backend-staging sh -c "cd /app && node -e \"const {runMigrations, pool} = require('./db/index'); runMigrations().then(() => pool.end())\""
# QA - Solo migraciones
docker-compose exec unosport-qa sh -c "cd /app/functions && node -e \"const {runMigrations, pool} = require('./db/index'); runMigrations().then(() => pool.end())\""
Ejecutar Migraciones en Contenedor Nuevo (antes de iniciar servidor)
Si necesitas ejecutar migraciones antes de iniciar el servidor, puedes usar un contenedor temporal:
# Staging - Ejecutar migraciones con contenedor temporal
docker-compose run --rm unosport-backend-staging sh -c "cd /app && node db/install.js"
# QA - Ejecutar migraciones con contenedor temporal
docker-compose run --rm unosport-qa sh -c "cd /app/functions && node db/install.js"
El flag --rm elimina automáticamente el contenedor después de ejecutar el comando.
Verificar Logs de Migración
Para ver los logs detallados de la ejecución de migraciones:
# Ver logs del backend durante inicio (muestra migraciones automáticas)
docker-compose logs unosport-backend-staging | grep -i migration
# Ver logs completos del backend
docker-compose logs unosport-backend-staging
# Seguir logs en tiempo real
docker-compose logs -f unosport-backend-staging
Solución de Problemas Comunes
Error: "Cannot connect to database"
Verifica que la base de datos esté corriendo y saludable:
# Verificar estado de base de datos
docker-compose ps unosport-db-staging
# Verificar salud de base de datos
docker-compose exec unosport-db-staging pg_isready -U unosport_admin
# Verificar variables de entorno en el contenedor
docker-compose exec unosport-backend-staging env | grep DB_
Error: "Migration already executed"
Este es un comportamiento normal. El sistema registra las migraciones ejecutadas en la tabla schema_migrations y no las ejecuta dos veces.
Error: "Permission denied"
Verifica que el usuario del contenedor tenga permisos adecuados. El contenedor se ejecuta con user: 10000:10000 por seguridad.
Re-ejecutar migraciones fallidas
Si una migración falló parcialmente, puedes verificar el estado y ejecutar manualmente:
# Ver estado de migraciones
docker-compose exec unosport-db-staging psql -U unosport_admin -d unosportclub_staging -c "SELECT * FROM schema_migrations ORDER BY id;"
# Ejecutar migraciones manualmente
docker-compose exec unosport-backend-staging sh -c "cd /app && node db/install.js"
Acceso a Base de Datos
Para acceder a una base de datos de un entorno:
# Staging
docker-compose exec unosport-db-staging psql -U unosport_admin -d unosportclub_staging
# QA
docker-compose exec unosport-db-qa psql -U unosport_admin -d unosportclub_qa
Backup de Base de Datos
# Backup de Staging
docker-compose exec unosport-db-staging pg_dump -U unosport_admin unosportclub_staging > backup_staging_$(date +%Y%m%d_%H%M%S).sql
# Backup de QA
docker-compose exec unosport-db-qa pg_dump -U unosport_admin unosportclub_qa > backup_qa_$(date +%Y%m%d_%H%M%S).sql
Monitoreo y Logs
Seguridad
Usuario no-root
Todos los servicios se ejecutan con usuario no-root (user: 10000:10000) para mayor seguridad.
Volúmenes de Solo Lectura
Los archivos de configuración se montan como solo lectura (:ro):
volumes:
- ./unosportclub/firebase/firebase-adminsdk.json:/firebase-adminsdk.json:ro
- ./unosportclub/.env:/app/.env:ro
Solución de Problemas
Servicio No Inicia
# Verificar logs
docker-compose logs unosport-backend-staging
# Verificar configuración
docker-compose config
# Verificar dependencias
docker-compose ps unosport-db-staging
Error de Conexión a Base de Datos
# Verificar que la base de datos esté saludable
docker-compose exec unosport-db-staging pg_isready -U unosport_admin
# Verificar variables de entorno
docker-compose exec unosport-backend-staging env | grep DB_
# Verificar conectividad de red
docker-compose exec unosport-backend-staging ping unosport-db-staging
Mejores Prácticas
Gestión de Versiones
-
Usar tags específicos en lugar de
latestpara producción -
Probar actualizaciones en QA antes de Staging
-
Probar en Staging antes de Production
Backups Regulares
-
Realizar backups diarios de bases de datos
-
Almacenar backups en ubicación segura
-
Probar restauración de backups periódicamente