Files
snatchgame/DEPLOYMENT.md
josedario87 87f5b09f4d
All checks were successful
build-and-deploy / filter (push) Successful in 2s
build-and-deploy / build (push) Successful in 5s
build-and-deploy / deploy (push) Successful in 10s
docs: Complete production documentation and deployment guide
- Add comprehensive DEPLOYMENT.md with Docker and CI/CD details
- Update README.md with production URLs and architecture diagrams
- Document v0.0.9-alpha changes in CHANGELOG.md with full feature list
- Enhance CLAUDE.md with production architecture and security practices
- Document SSE optimizations, URL separation, and monitoring setup
- Include troubleshooting guides and maintenance commands
- Add network architecture diagrams and communication flows
2025-07-05 17:18:25 -06:00

12 KiB

🚀 Guía de Deployment - SnatchGame

📋 Resumen

Este documento detalla el proceso completo de deployment de SnatchGame en producción usando Docker, Gitea Actions y Nginx Proxy Manager.

🏗️ Arquitectura de Producción

Componentes del Sistema

┌────────────────────────────────────────────────────────────────┐
│                    Nginx Proxy Manager                        │
│                    (Red "principal")                          │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  🌐 snatchGame.interno.com ──► snatchgame-client:3000         │
│  🎯 snatchGameServer.interno.com ──► snatchgame-server:2567   │  
│  📊 snatchgGameAdmin.interno.com ──► snatchgame-admin:3001    │
│                                                                │
└────────────────────────────────────────────────────────────────┘

Servicios Docker

Servicio Imagen Puerto Interno Puerto Externo Descripción
snatchgame-server gitea.interno.com/nucleo000/snatchgame-server:latest 2567 3067 Servidor Colyseus
snatchgame-client gitea.interno.com/nucleo000/snatchgame-client:latest 3000 3010 Cliente Vue + Express
snatchgame-admin gitea.interno.com/nucleo000/snatchgame-admin:latest 3001 3011 Admin Vue + Express

🔧 Configuración de URLs

Separación Interna/Externa

El sistema utiliza una arquitectura de doble URL para optimizar la comunicación:

URLs Externas (HTTPS)

  • Propósito: Comunicación navegador ↔ servicios
  • Protocolo: HTTPS/WSS (seguro)
  • Destino: Nginx Proxy Manager
Cliente Frontend → https://snatchGameServer.interno.com (WebSocket)
Admin Frontend → https://snatchGameServer.interno.com (Fetch API)

URLs Internas (HTTP)

  • Propósito: Comunicación contenedor ↔ contenedor
  • Protocolo: HTTP (rápido, sin SSL)
  • Destino: Directo entre contenedores
Admin Server → http://snatchgame-server:2567 (SSE, Control API)
Client Server → http://snatchgame-server:2567 (Health checks)

Variables de Entorno

# En docker-compose.yml
environment:
  - NODE_ENV=production
  - SERVER_URL=http://snatchgame-server:2567          # URL interna
  - PUBLIC_SERVER_URL=https://snatchGameServer.interno.com  # URL externa

🐳 Docker Configuration

Dockerfiles

Servidor (server/Dockerfile)

FROM node:20-alpine
RUN apk add --no-cache git wget
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build && npm prune --production
EXPOSE 2567
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=40s \
  CMD wget --no-verbose --tries=1 --spider http://localhost:2567/health || exit 1
CMD ["npm", "start"]

Cliente y Admin (client/Dockerfile, admin/Dockerfile)

FROM node:20-alpine
RUN apk add --no-cache git wget
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build:prod  # Skips type generation in Docker
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=40s \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["npm", "start"]

Docker Compose

version: '3.8'

services:
  snatchgame-server:
    image: gitea.interno.com/nucleo000/snatchgame-server:latest
    container_name: snatchgame-server
    ports:
      - "3067:2567"
    environment:
      - NODE_ENV=production
      - PORT=2567
    networks:
      - principal
      - snatchgame-network
    restart: unless-stopped

  snatchgame-client:
    image: gitea.interno.com/nucleo000/snatchgame-client:latest
    container_name: snatchgame-client
    ports:
      - "3010:3000"
    environment:
      - NODE_ENV=production
      - PORT=3000
      - SERVER_URL=http://snatchgame-server:2567
      - PUBLIC_SERVER_URL=https://snatchGameServer.interno.com
    depends_on:
      - snatchgame-server
    networks:
      - principal
      - snatchgame-network
    restart: unless-stopped

  snatchgame-admin:
    image: gitea.interno.com/nucleo000/snatchgame-admin:latest
    container_name: snatchgame-admin
    ports:
      - "3011:3001"
    environment:
      - NODE_ENV=production
      - PORT=3001
      - SERVER_URL=http://snatchgame-server:2567
      - PUBLIC_SERVER_URL=https://snatchGameServer.interno.com
    depends_on:
      - snatchgame-server
    networks:
      - principal
      - snatchgame-network
    restart: unless-stopped

networks:
  principal:
    external: true
  snatchgame-network:
    driver: bridge

⚙️ CI/CD Pipeline

Gitea Actions (.gitea/workflows/build-and-deploy.yml)

name: Build and Deploy SnatchGame

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build-server:
    runs-on: ubuntu-latest
    if: contains(github.event.head_commit.modified, 'server/') || github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - name: Build and push server image
        run: |
          docker build -t gitea.interno.com/nucleo000/snatchgame-server:latest ./server
          docker push gitea.interno.com/nucleo000/snatchgame-server:latest

  build-client:
    runs-on: ubuntu-latest  
    if: contains(github.event.head_commit.modified, 'client/') || github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
      - name: Build and push client image
        run: |
          docker build -t gitea.interno.com/nucleo000/snatchgame-client:latest ./client
          docker push gitea.interno.com/nucleo000/snatchgame-client:latest

  build-admin:
    runs-on: ubuntu-latest
    if: contains(github.event.head_commit.modified, 'admin/') || github.event_name == 'pull_request'  
    steps:
      - uses: actions/checkout@v4
      - name: Build and push admin image
        run: |
          docker build -t gitea.interno.com/nucleo000/snatchgame-admin:latest ./admin
          docker push gitea.interno.com/nucleo000/snatchgame-admin:latest

  deploy:
    runs-on: ubuntu-latest
    needs: [build-server, build-client, build-admin]
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: |
          docker-compose down
          docker-compose pull
          docker-compose up -d

Conditional Building

El pipeline utiliza conditional building basado en archivos modificados:

  • server/ → Builds snatchgame-server
  • client/ → Builds snatchgame-client
  • admin/ → Builds snatchgame-admin
  • Pull requests → Builds todo pero no deploya

🔄 Optimizaciones SSE

Problema Identificado

La comunicación SSE entre el navegador y los contenedores Docker presentaba latencia alta (~10 segundos entre actualizaciones).

Solución Implementada

Headers Anti-Buffering

// admin/server.js
res.writeHead(200, {
  'Content-Type': 'text/event-stream',
  'Cache-Control': 'no-cache, no-store, must-revalidate',
  'Connection': 'keep-alive',
  'X-Accel-Buffering': 'no',        // Disable nginx buffering
  'Content-Encoding': 'identity'     // Disable compression
});

Polling Optimizado

// Reducido de 500ms a 250ms para updates más rápidos
const pollInterval = setInterval(async () => {
  // Fetch game stats...
}, 250);

Heartbeat Mechanism

// Keepalive cada 30 segundos
const heartbeatInterval = setInterval(() => {
  res.write(': heartbeat\n\n');
}, 30000);

Auto-reconexión Cliente

// admin/src/services/adminService.ts
this.eventSource.onerror = (error) => {
  // Auto-reconnect after 5 seconds
  setTimeout(() => {
    if (!this.isConnected) {
      this.connect(this.callback!);
    }
  }, 5000);
};

🚀 Proceso de Deployment

1. Push a Main Branch

git add .
git commit -m "feature: new functionality"
git push gitea main

2. Automatic CI/CD

  • Gitea Actions detecta cambios
  • Builds las imágenes necesarias
  • Push al registry interno
  • Deploy automático en producción

3. Verificación

# Verificar estado de contenedores
docker-compose ps

# Ver logs en tiempo real
docker-compose logs -f

# Health check manual
curl -f http://localhost:3067/health
curl -f http://localhost:3010/health  
curl -f http://localhost:3011/health

4. Rollback si es Necesario

# Rollback a versión anterior
docker-compose down
git checkout <previous-commit>
docker-compose up -d --build

🔧 Comandos de Mantenimiento

Development to Production

# Build local para testing
docker-compose build

# Deploy en producción
docker-compose up -d

# Rebuild completo tras cambios
docker-compose down && docker-compose up -d --build

Monitoring

# Logs de servicio específico
docker-compose logs -f snatchgame-server
docker-compose logs -f snatchgame-client
docker-compose logs -f snatchgame-admin

# Estadísticas de recursos
docker stats

# Estado de redes
docker network ls
docker network inspect snatchgame_principal

Troubleshooting

# Verificar conectividad entre contenedores
docker exec snatchgame-admin curl http://snatchgame-server:2567/health

# Reiniciar servicio específico
docker-compose restart snatchgame-admin

# Limpiar imágenes antiguas
docker image prune -f

📊 Monitoring y Salud del Sistema

Health Checks

Todos los servicios incluyen health checks automáticos:

healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:2567/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Logs Estructurados

// Logs con timestamps y prefijos para debugging
console.log(`[SSE] Connection #${connectionId} established. Total: ${sseConnections}`);
console.log(`[SSE] Stats fetched successfully in ${fetchTime}ms`);

Métricas de Rendimiento

  • SSE Update Frequency: 250ms
  • Heartbeat Interval: 30s
  • Auto-reconnect Delay: 5s
  • Health Check Interval: 30s

🔒 Seguridad

HTTPS/WSS

  • Todas las comunicaciones externas usan HTTPS/WSS
  • Certificados SSL manejados por Nginx Proxy Manager
  • Comunicación interna HTTP (rápida y segura dentro de Docker)

Network Isolation

  • Red principal: Comunicación con Nginx
  • Red snatchgame-network: Comunicación interna entre servicios
  • Puertos expuestos mínimos

Environment Variables

  • Configuración sensitive via variables de entorno
  • Separación clara desarrollo/producción
  • No secrets hardcoded en código

📈 Escalabilidad

Horizontal Scaling

# Múltiples instancias del mismo servicio
snatchgame-server-1:
  image: gitea.interno.com/nucleo000/snatchgame-server:latest
  # ...
snatchgame-server-2:
  image: gitea.interno.com/nucleo000/snatchgame-server:latest
  # ...

Load Balancing

  • Nginx Proxy Manager puede distribuir carga
  • Health checks aseguran disponibilidad
  • Auto-restart en caso de fallas

🎯 Próximos Pasos

  1. Monitoring Avanzado: Prometheus + Grafana
  2. Backup Automático: Estrategia de backups de datos
  3. Blue-Green Deployment: Deploy sin downtime
  4. Resource Limits: CPU/Memory limits por contenedor
  5. Log Aggregation: ELK Stack o similar

📝 Nota: Esta documentación refleja el estado actual del sistema al 2025-07-05. Actualizar tras modificaciones significativas.