Docker, Monitoring e Scaling

Dal Development alla Production: Build Once, Deploy Everywhere

Hai costruito tutti i pezzi. Un backend robusto con i pattern RAD-System, un frontend Angular accattivante, workflow orchestrati e un sistema flessibile di LLM provider switching. Ora passiamo all'infrastruttura: come distribuire, scalare e monitorare in modo affidabile questo sistema in production?

Questo articolo rappresenta il ponte tra l'architettura e le operazioni. Docker, Docker Compose, parità degli ambienti, health checks, monitoring e le strategie di scaling che ti permettono di gestire da 10 a 10.000 utenti.

La Filosofia del Deployment: Distribuzione basata su Artifact

Il Sistema RAG segue un principio rigoroso: build once, deploy everywhere (costruisci una volta, distribuisci ovunque).


┌─────────────────────────────────────┐
│   Development Environment           │
│   npm run build                     │
│   npm test                          │
│   Docker build                      │
└──────────────┬──────────────────────┘
               │
               ▼
      ┌────────────────┐
      │   Docker Image │
      │ (immutable)    │
      └────────┬───────┘
               │
      ┌────────┴──────────────────┬─────────────┐
      ▼                           ▼             ▼
┌──────────┐              ┌──────────┐   ┌──────────┐
│   Dev    │              │  Staging │   │   Prod   │
│   env    │              │   env    │   │   env    │
│ (custom) │              │ (mirrored)   │ (locked) │
└──────────┘              └──────────┘   └──────────┘

Lo stesso artifact viene usato ovunque. Cambiano solo le environment variables e i secrets.

Architettura Docker Compose

Il Docker Compose del sistema orchestra tutti i servizi:



# Core services

services:
  # Qdrant: Vector database
  qdrant:
    image: qdrant/qdrant:v1.16
    ports: ["6333:6333", "6334:6334"]
    volumes: ["./Volumes/qdrant:/qdrant/storage"]
    networks: ["rag_network"]

  # PostgreSQL: Relational data
  postgresdb:
    image: postgres:16-alpine
    ports: ["5432:5432"]
    volumes: ["./Volumes/postgres:/var/lib/postgresql/data"]
    networks: ["rag_network"]

  # Redis: Caching & sessions
  redis:
    image: redis:7-alpine
    ports: ["6379:6379"]
    volumes: ["./Volumes/redis:/data"]
    networks: ["rag_network"]

  # n8n: Workflow orchestration
  n8n:
    build: "./Images/n8n"
    ports: ["5678:5678"]
    volumes: ["./Volumes/n8n:/home/node/.n8n"]
    networks: ["rag_network"]

  # FastAPI: NLP services
  fastapi:
    build: "./Images/fastapi"
    ports: ["8000:8000"]
    environment:
      - EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
      - MAX_WORKERS=4
    networks: ["rag_network"]

  # NestJS Backend
  backend:
    build: "./Images/backend"
    ports: ["3000:3000"]
    environment:
      - DATABASE_URL=postgres://user:pass@postgresdb:5432/rag
      - REDIS_URL=redis://:password@redis:6379
      - N8N_BASE_URL=http://n8n:5678
    networks: ["rag_network"]
    depends_on:
      - postgresdb
      - redis
      - n8n

  # Angular Frontend (dev server)
  frontend:
    build: "./Images/frontend"
    ports: ["4200:4200"]
    networks: ["rag_network"]

networks:
  rag_network:
    driver: bridge

Principi chiave:

  • Nessun database esterno: Tutto è autocontenuto
  • Bind mounts: I dati persistono ai riavvii tramite volumi del filesystem
  • Isolamento della rete: I servizi comunicano via Docker network
  • Environment variables: Configurazione esterna alle immagini

Processo di Build: Build Scripts

La directory DevOps/builder/ contiene script di build pronti per la produzione:



# Build backend

./DevOps/builder/build-be.sh dist

# Build frontend

./DevOps/builder/build-fe.sh prod

# Build Docker immagini

docker-compose build

# Oppure build di servizi specifici

docker-compose build backend fastapi

Backend Build Pipeline


#!/bin/bash

# 1. Compila TypeScript

npm run build

# 2. Rimuove le dev dependencies

npm ci --only=production

# 3. Copia nel Docker volume

cp -r dist node_modules ./Volumes/backend/app/

# 4. Crea un tarball versionato

tar czf ./update/backend-v1.0.0.tar.gz -C ./Volumes/backend .

echo "✅ Backend built: backend-v1.0.0.tar.gz"

Perché i tarball?

  • Versioning: Ogni release è un artifact immutabile
  • Rollback: Ripristino rapido alla versione precedente
  • Offline deployment: Nessuna necessità di registry npm durante il deployment

Configurazione dell'Ambiente

Ogni ambiente (dev, staging, prod) ha il proprio file .env:

.env.prod:


NODE_ENV=production
DEBUG=false
DATABASE_URL=postgres://prod_user:{REDIS_PASSWORD}@redis-prod:6379
JWT_SECRET=${PROD_JWT_SECRET}  # Da vault
LOG_LEVEL=warn
RATE_LIMIT=1000  # Richieste per minuto

Health Checks e Auto-Healing

Ogni container dichiara il proprio stato di salute:


services:
  backend:
    image: rag-backend:latest
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Docker rimuove e riavvia automaticamente i container che falliscono gli health checks.

Strategie di Scaling

Horizontal Scaling: Multiple Workers

Per il servizio FastAPI, che richiede molte risorse computazionali:


services:
  fastapi:
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 1G

Vertical Scaling: Resource Limits

Vincoli delle risorse Docker:


services:
  backend:
    deploy:
      resources:
        limits:
          cpus: "1"      # Max 1 CPU core
          memory: 512M   # Max 512MB RAM

Monitoring e Logging

Application Health Dashboard

Le metriche in tempo reale sono esposte su /metrics (formato Prometheus):


@Get('/metrics')
@Public()
async getMetrics(): Promise<string> {
  const metrics = {
    'rag_query_duration_seconds': this.queryDurations,
    'rag_embedding_errors_total': this.embeddingErrors,
    // ...
  };
  return formatPrometheus(metrics);
}

Workflow di Deployment

Blue-Green Deployment

Mantenere due versioni di produzione attive contemporaneamente per azzerare il downtime:



# Versione corrente: Blue (v1.2.0)

# Nuova versione: Green (v1.3.0)

# Deploy su green

docker-compose -f docker-compose-green.yml up -d

# Switch del traffico tramite nginx

nginx.conf: upstream producer -> green
systemctl reload nginx

Checklist per il Deployment in Production


Security
  ☐ Tutti i secrets in environment/vault (non nel .env)
  ☐ HTTPS/TLS abilitato
  ☐ Password dei database robuste
  ☐ Firewall con restrizione delle porte

Infrastructure
  ☐ Resource limits impostati (CPU, memory)
  ☐ Health checks configurati
  ☐ Backup dello storage automatizzato (giornaliero)
  ☐ Monitoring e alert attivi

Sintesi Finale

Con questo articolo si conclude la serie sul Sistema RAG. Abbiamo esplorato:

  1. Architettura & Privacy - Il "perché" dietro le scelte di design
  2. n8n Workflows - Orchestrazione di operazioni complesse
  3. Vector Embeddings - Ricerca semantica su scala
  4. FastAPI NLP - Il motore NLP in Python
  5. NestJS Backend - API enterprise con RAD-System
  6. Angular Frontend - Interfaccia chat responsive
  7. Provider Switching - Flessibilità LLM senza lock-in
  8. DevOps & Scaling - Portare il sistema in produzione

---

Punti Chiave:

Artifact-based builds = Deployment riproducibili e affidabili

Docker Compose = Infrastruttura semplificata

Health checks = Sistemi auto-rigeneranti (self-healing)

Resource limits = Prestazioni stabili e prevedibili

Monitoring = Visibilità sulla salute del sistema

Ora hai un sistema RAG pronto per la produzione, scalabile, resiliente e manutenibile.

---

GitHub:

Grazie per aver seguito questa serie. Il futuro dell'AI non riguarda solo i modelli, ma i sistemi che sono comprensibili, manutenibili e tuoi. 🚀