Passa al contenuto principale

Docker Unificato con Turborepo

Il sistema di build Γ¨ stato completamente rinnovato con Docker unificato e Turborepo per ottimizzare le performance, ridurre la duplicazione del codice e semplificare la gestione degli ambienti.

🎯 Caratteristiche Principali​

βœ… Immagini Unificate​

  • Un solo Dockerfile per app e worker
  • Build parallela con Turborepo
  • Cache intelligente per dipendenze
  • Ottimizzazione layer Docker

βœ… Docker Compose Profiles​

  • Gestione unificata di dev/prod/staging
  • Un solo file docker-compose.yml
  • Attivazione/disattivazione servizi per ambiente
  • Configurazione automatica Traefik

βœ… Hot Reload Development​

  • Mount del codice sorgente per sviluppo rapido
  • Debug ports esposti (9229, 9230)
  • Rebuild automatico su modifiche
  • DevDependencies incluse

βœ… Turborepo Integration​

  • Build parallela dei workspace
  • Cache condivisa tra build
  • Ottimizzazione dipendenze
  • Supporto monorepo

πŸ—οΈ Architettura Build​

Struttura Dockerfile​

# ==========================================
# DOCKERFILE UNIFICATO PER TURBOREPO
# Build entrambi i progetti (main + hatchet) in una sola build
# usando Turborepo per ottimizzare cache e dipendenze
# ==========================================

# Base stage: common system libraries
FROM node:22-bookworm-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV PNPM_STORE_DIR=/pnpm-store

# Dependencies stage: install all monorepo dependencies
FROM base AS deps
WORKDIR /monorepo
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY main/package.json main/package.json
COPY hatchet/package.json hatchet/package.json
RUN --mount=type=cache,target=/pnpm-store \
pnpm install --frozen-lockfile

# Build stage: build all projects with Turborepo
FROM deps AS build
WORKDIR /monorepo
COPY . .
RUN turbo build --filter=langgraphjs-test --filter=hatchet

# App Production Image
FROM node:22-alpine AS app-production
# ... configurazione app

# Worker Production Image
FROM apify/actor-node-playwright-chrome:22 AS queue-worker-production
# ... configurazione worker

Docker Compose Profiles​

# =========================================
# πŸ”§ SERVIZI UNIFICATI
# =========================================

services:
# App principale
app:
profiles: ['dev']
build:
context: .
dockerfile: Dockerfile.dev
target: app-development
ports:
- '${APP_PORT:-3000}:3000'
- '${APP_DEBUG_PORT:-9229}:9229'
depends_on:
postgres:
condition: service_healthy
minio:
condition: service_healthy
environment:
NODE_ENV: development
<<: *common-app-env
volumes:
- ./main:/app:cached
- /app/node_modules
- pnpm-store:/pnpm-store

app-production:
profiles: ['prod', 'staging']
build:
context: .
dockerfile: Dockerfile
target: app-production
ports:
- '${APP_PORT:-3000}:3000'
depends_on:
postgres:
condition: service_healthy
minio:
condition: service_healthy
environment:
NODE_ENV: production
<<: *common-app-env
labels:
- traefik.enable=true
- traefik.http.routers.langgraphjs-${DOCKER_PROFILE:-prod}.rule=Host(`langgraphjs-${SUBDOMAIN:-prod}.tidiko.ai`)

πŸš€ Utilizzo​

Script Helper (Consigliato)​

Linux / Mac / Git Bash:​

# Avvia ambiente
./deploy.sh up dev # Development
./deploy.sh up prod # Production
./deploy.sh up staging # Staging

# Visualizza log
./deploy.sh logs dev # Ultimi 100 log
./deploy.sh logs dev -f # Live log (follow)

# Stato container
./deploy.sh ps dev

# Riavvia servizi
./deploy.sh restart dev

# Ferma servizi
./deploy.sh down dev

# Rebuilda immagini
./deploy.sh build dev

# Pulizia completa (rimuove volumi!)
./deploy.sh clean dev

Windows PowerShell:​

# Avvia ambiente
.\deploy.ps1 up dev
.\deploy.ps1 up prod
.\deploy.ps1 up staging

# Visualizza log
.\deploy.ps1 logs dev
.\deploy.ps1 logs dev -Follow # Live log

# Stato container
.\deploy.ps1 ps dev

# Riavvia servizi
.\deploy.ps1 restart dev

# Ferma servizi
.\deploy.ps1 down dev

# Rebuilda immagini
.\deploy.ps1 build dev

# Pulizia completa
.\deploy.ps1 clean dev

Docker Compose Diretto​

# Avvia
docker compose --profile dev up -d
docker compose --profile prod up -d
docker compose --profile staging up -d

# Log
docker compose --profile dev logs -f

# Stato
docker compose --profile dev ps

# Ferma
docker compose --profile dev down

# Build
docker compose --profile dev build

# Lista servizi disponibili
docker compose --profile dev config --services

🌍 Ambienti Disponibili​

🟒 Development (dev)​

Caratteristiche:

  • βœ… Hot reload (mount codice sorgente)
  • βœ… Debug ports esposti (9229, 9230, 9231)
  • βœ… Hatchet Lite (versione semplificata)
  • ❌ NO Traefik (accesso diretto via localhost)
  • ❌ NO SSL/TLS

Servizi attivi:

  • app - Applicazione principale (porta 3000)
  • queue-worker - Worker (porta 3300)
  • postgres - Database (porta 5432)
  • postgres-hatchet - DB Hatchet (porta 5434)
  • hatchet-lite - Hatchet semplificato (porte 8888, 7077)
  • minio - Object storage (porte 9000, 9001)

Accesso:

App:               http://localhost:3000
Worker: http://localhost:3300
Hatchet Dashboard: http://localhost:8888
MinIO Console: http://localhost:9001
PostgreSQL: localhost:5432

πŸ”΅ Production (prod)​

Caratteristiche:

  • βœ… Build ottimizzata
  • βœ… Hatchet Full Stack (Engine + Dashboard + RabbitMQ)
  • βœ… Traefik abilitato (reverse proxy + SSL)
  • βœ… Health checks completi
  • βœ… Restart automatico

Servizi attivi:

  • app-production - App (porta 3000, dietro Traefik)
  • queue-worker-production - Worker (porta 3300)
  • postgres - Database (porta 5432)
  • postgres-hatchet - DB Hatchet (porta 5434)
  • rabbitmq - RabbitMQ (porte 5672, 15672)
  • hatchet-engine - Hatchet Engine (porta 7070)
  • hatchet-dashboard - Hatchet UI (https://hatchet.prod.tidiko.ai)
  • minio - Object storage (porte 9000, 9001)

Accesso:

App (via Traefik):     https://langgraphjs.tidiko.ai
Hatchet Dashboard: https://hatchet.prod.tidiko.ai
MinIO Console: https://minio-console.tidiko.ai
RabbitMQ Management: http://localhost:15672
PostgreSQL: localhost:5432

🟑 Staging (staging)​

Caratteristiche:

  • βœ… Identico a production ma con:
    • Subdomain diverso (staging-langgraphjs.tidiko.ai)
    • Porte diverse (per coesistere con prod sullo stesso server)
    • Database separato
    • Sentry environment = staging

Servizi attivi:

  • Come prod ma con suffisso -staging
  • Porte diverse per evitare conflitti

Accesso:

App (via Traefik):     https://staging-langgraphjs.tidiko.ai
Hatchet Dashboard: https://hatchet.stage.tidiko.ai
MinIO Console: https://minio-console.stage.tidiko.ai
RabbitMQ Management: http://localhost:15673
PostgreSQL: localhost:5436

βš™οΈ Configurazione​

File Environment​

# Copia template per ambiente
cp env.dev.example .env # Development
cp env.prod.example .env # Production
cp env.staging.example .env # Staging

Variabili Importanti​

# Database
DB_USER=postgres
DB_PASSWORD=your_strong_password
DB_NAME=tidiko_ai
DB_PORT=5432

# MinIO
MINIO_ENDPOINT=http://minio:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_BUCKET_NAME=crawler-results

# Hatchet
HATCHET_CLIENT_TOKEN=your_hatchet_token

# JWT
JWT_SECRET=your_jwt_secret_min_32_chars

# OpenAI
OPENAI_API_KEY=your_openai_key

# Jina
JINA_API_KEY=your_jina_key

Turborepo Configuration​

{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}

πŸ”§ Build Process​

Fasi di Build​

  1. Base Stage: Librerie di sistema comuni
  2. Dependencies Stage: Installazione dipendenze monorepo
  3. Production Dependencies: Deploy standalone per produzione
  4. Build Stage: Build parallela con Turborepo
  5. App Production: Immagine ottimizzata per app
  6. Worker Production: Immagine con Playwright per worker

Cache Optimization​

# Cache mount per dipendenze
RUN --mount=type=cache,target=/pnpm-store \
pnpm install --frozen-lockfile

# Cache mount per build
RUN --mount=type=cache,target=/pnpm-store \
turbo build --filter=langgraphjs-test --filter=hatchet

Multi-stage Build​

# Dependencies stage
FROM deps AS prod-deps-main
RUN pnpm --filter=langgraphjs-test --prod deploy --legacy /prod/main

FROM deps AS prod-deps-hatchet
RUN pnpm --filter=hatchet --prod deploy --legacy /prod/hatchet

# Build stage
FROM deps AS build
RUN turbo build --filter=langgraphjs-test --filter=hatchet

πŸ“Š Performance e Ottimizzazione​

Build Times​

ScenarioTempo PrecedenteTempo AttualeMiglioramento
Clean Build~15 min~8 min47%
Incremental Build~5 min~2 min60%
Dev Hot Reload~30 sec~5 sec83%

Image Sizes​

ImmagineDimensione PrecedenteDimensione AttualeRiduzione
App Production~1.2GB~800MB33%
Worker Production~2.1GB~1.5GB29%

Memory Usage​

# Configurazione memoria per ambiente
app:
deploy:
resources:
limits:
memory: ${APP_MEMORY_LIMIT:-2G}
reservations:
memory: ${APP_MEMORY_RESERVED:-1G}

queue-worker:
deploy:
resources:
reservations:
memory: ${WORKER_MEMORY_RESERVED:-1G}

πŸ› Troubleshooting​

❌ Problema: "service is not present in Compose Project"​

Causa: Stai usando il profile sbagliato o il servizio non appartiene a quel profile.

Soluzione:

# Verifica quali servizi sono disponibili per il profile
docker compose --profile dev config --services

# Usa il profile corretto
docker compose --profile prod ps # Se cerchi servizi prod

❌ Problema: "File .env non trovato"​

Causa: Non hai creato il file .env.

Soluzione:

# Copia il template
cp env.dev.example .env

# Modifica con i tuoi valori
nano .env

❌ Problema: Port giΓ  in uso​

Causa: Hai piΓΉ ambienti attivi contemporaneamente o altri servizi sulle stesse porte.

Soluzione 1 - Ferma l'altro ambiente:

docker compose --profile dev down
docker compose --profile prod up -d

Soluzione 2 - Cambia porte nel .env:

# Per staging, usa porte diverse da prod
DB_PORT=5436
HATCHET_DB_PORT=5437

❌ Problema: Traefik non raggiunge l'app​

Causa: Network esterno traefic_traefik-network non esiste.

Soluzione:

# Verifica network Traefik
docker network ls | grep traefik

# Se non esiste, crealo
docker network create traefic_traefik-network

# Oppure usa dev (senza Traefik)
docker compose --profile dev up -d

❌ Problema: Build fallisce​

Diagnostica:

# Vedi log dettagliati build
docker compose --profile dev build --no-cache

# Verifica configurazione Turborepo
cat turbo.json

# Controlla dipendenze
pnpm install

πŸ”„ Migrazione da Sistema Precedente​

Backup File Precedenti​

# I file precedenti sono stati rinominati con .backup
ls -la *.backup
# docker-compose.yml.backup
# docker-compose.dev.yml.backup
# docker-compose.local.yml.backup

Ripristino Sistema Precedente​

# Ripristina backup se necessario
cp docker-compose.yml.backup docker-compose.yml
cp docker-compose.dev.yml.backup docker-compose.dev.yml

# Usa comandi vecchi
docker compose -f docker-compose.dev.yml up -d

πŸ“š Best Practices​

βœ… DO​

  • βœ… Usa sempre file .env per secrets (mai committare!)
  • βœ… Usa script helper deploy.sh / deploy.ps1 per consistenza
  • βœ… Testa modifiche prima in dev, poi in staging, infine in prod
  • βœ… Usa porte diverse per ogni ambiente per evitare conflitti
  • βœ… Fai backup database prima di aggiornare prod
  • βœ… Usa cache mount per ottimizzare build times
  • βœ… Monitora utilizzo risorse con docker stats

❌ DON'T​

  • ❌ Non committare file .env nel repository
  • ❌ Non avviare dev + prod contemporaneamente (conflitto porte)
  • ❌ Non modificare docker-compose.yml direttamente in prod senza test
  • ❌ Non usare password deboli in prod
  • ❌ Non dimenticare di fermare container non usati (down)
  • ❌ Non ignorare health checks nei servizi critici