Progettato Per Essere Semplice in Produzione

Una delle cose che ho imparato attraverso molti progetti è che la complessità del deployment uccide la manutenzione. Se mettere una nuova versione in live richiede a qualcuno di ricordare una sequenza di passaggi, connettersi a più server, o avere la toolchain di build installata in produzione — le cose prima o poi andranno male.

La configurazione Docker di RAD-System è costruita attorno a un principio: i server di produzione dovrebbero essere il più stupidi possibile. Eseguono container. Non compilano codice. Il codice è su GitHub.

1. Lo Stack Containerizzato

L'intero sistema è orchestrato da un singolo docker-compose.yml. Ogni servizio viene eseguito in isolamento su una rete interna dedicata rad_network — il database non è mai esposto a internet pubblico. Solo le porte di cui l'applicazione ha bisogno vengono aperte.

La persistenza dei dati è gestita tramite montaggi di volume espliciti:

  • ./Volumes/postgres — i dati del database sopravvivono ai riavvii del container e alle ricostruzioni
  • ./Config/backend/.env — le variabili di ambiente vengono iniettate al runtime, mai incorporate nell'immagine

2. PostgreSQL: Auto-Inizializzazione e Configurazione Personalizzata

Al primo avvio, il container PostgreSQL esegue qualsiasi script SQL o shell trovato in ./Config/postgres/init/, montato su /docker-entrypoint-initdb.d/. Questo crea utenti, database e installa estensioni automaticamente — nessun intervento manuale dopo il primo docker compose up.

File personalizzati postgresql.conf e pg_hba.conf sovrascrivono i default per corrispondere ai requisiti di performance e sicurezza specifici del sistema.

3. Hot Reload in Sviluppo, Configurazione Runtime in Produzione

Durante lo sviluppo, il codice sorgente del backend viene montato direttamente nel container tramite ./Volumes/backend/app. I cambiamenti al codice nel host attivano hot-reload dentro il container — il ciclo di sviluppo è veloce senza alcun tooling speciale.

Il frontend viene servito da Nginx. Il file app-config.json viene montato al runtime, non compilato nell'immagine. Cambiare l'URL dell'API in produzione significa modificare un file JSON e riavviare il container del frontend — nessuna ricostruzione.

4. Deployment Basato su Artifact: La Strategia Che Ha Eliminato Il Mio Build Server

Questa è la parte del sistema di cui sono più soddisfatto operativamente. I pipeline tradizionali CI/CD ricostruiscono le immagini Docker per ogni release. Questo richiede Node.js, npm e build tools sul server CI o dentro l'immagine. È lento, è complesso, e lega il tuo deployment all'infrastruttura di build.

RAD-System usa una strategia diversa: le immagini Docker sono runtimes statici. Il codice dell'applicazione è un artifact — un tarball versionato — iniettato tramite volumi.

Come funziona una release:

  1. Costruisci localmentebuild-be.sh e build-fe.sh compilano il codice e producono un tarball versionato (es. rad-backend-1.0.2.tgz)
  2. Carica l'artifact sul server di produzione
  3. Deploy:
docker compose stop backend
tar -xzf rad-backend-1.0.2.tgz -C ./Volumes/backend/app
docker compose up -d backend

Cosa significa questo in pratica:

  • Nessun build tool in produzione — il server esegue container, nient'altro
  • Rollback istantaneo — estrai il tarball precedente, riavvia il container
  • Immagini pulite — le immagini Docker cambiano solo quando il runtime (versione Node, config Nginx) cambia, non ad ogni cambio di codice
  • Deploy veloce — estrarre un tarball è questione di secondi, non minuti

Ho usato questo pattern per anni. Funziona in modo affidabile, è facile automatizzarlo con un semplice script shell se necessario, ed è facile capire quando qualcosa va male.