Per correttezza, dovrei iniziare dicendo che sono nuovo sulla piattaforma e nel codice sorgente, quindi non ho idea di come funziona attualmente rebuild sotto il cofano. Tuttavia, la mia comprensione attuale è che rebuild:
ferma il contenitore corrente
costruisce un nuovo contenitore con i dati dall’albero sorgente
attende che tu avvii il nuovo contenitore
Da una prospettiva orientata al DevOps, perché non è possibile costruire il nuovo contenitore (forse in un altro branch o directory temporanea) mentre quello vecchio è ancora in esecuzione? Sembra che questo renderebbe lo scambio del nuovo contenitore con quello vecchio un processo molto più veloce (almeno in termini di tempo di inattività), forse dell’ordine di secondi invece di minuti.
Se i contenitori utilizzano volumi di archiviazione che non vengono distrutti quando il contenitore viene ricostruito, non sono nemmeno sicuro che le modifiche alla configurazione o al database (ad esempio nuovi messaggi) debbano essere gestite in modo speciale per questo caso d’uso, il che significa che la costruzione del contenitore non dovrebbe essere così strettamente accoppiata allo stato del contenitore.
Si tratta semplicemente di un problema che nessuno ha ancora affrontato, o esiste una decisione architetturale esistente che richiede che un contenitore venga fermato prima che un altro possa essere costruito?
Aggiornare le dipendenze a livello di sistema operativo, come la versione principale di Ruby
Aggiornare a versioni più recenti e incompatibili di PostgreSQL, gestendo automaticamente l’aggiornamento del formato del disco dati per la nuova versione
Aggiornare l’immagine Docker. Ad esempio, all’inizio di quest’anno siamo passati da Ubuntu 16.04 all’ultima versione di Debian, e tutto è trasparente per l’utente: basta digitare ./launcher rebuild app.
I rebuild non sono necessari in ogni momento; sono obbligatori solo alcune volte l’anno quando avviene un aggiornamento massiccio delle dipendenze. Per tutti gli altri aggiornamenti, è possibile eseguire aggiornamenti senza interruzioni (zero downtime) cliccando sull’aggiornatore web nell’interfaccia di amministrazione.
Per ulteriori punti di tipo “devops”, puoi provare:
Potrei sbagliarmi, ma ritengo che la domanda di @CodeGnome sui rebuild a downtime zero meriti ancora un’ulteriore indagine.
Se ho capito correttamente Docker, i seguenti aspetti di Discourse potrebbero essere ricostruiti in background in un nuovo container mentre quello esistente è ancora in esecuzione:
Aggiornare il codice sorgente di Discourse
Aggiornare le dipendenze a livello di sistema operativo, come la versione principale di Ruby
Aggiornare l’immagine Docker. Solo come esempio, all’inizio di quest’anno siamo passati da Ubuntu 16.04 all’ultima Debian e tutto è stato trasparente per l’utente; basta digitare ./launcher rebuild app.
Per quanto riguarda le modifiche che rompono la compatibilità di PostgreSQL, la questione è più delicata a causa del volume dei dati, che, presumo, è condiviso tra il vecchio e il nuovo container.
Forse il sito potrebbe essere messo in modalità sola lettura all’inizio del rebuild, con il vecchio container che mantiene il suo volume esistente, mentre il database in costruzione potrebbe operare all’interno di un nuovo volume Docker?
Per quanto riguarda l’aggiornamento del codice sorgente di Discourse, delle dipendenze a livello di sistema operativo, dell’immagine base Docker, dei gem Ruby e di elementi simili, è possibile procedere eseguendo la build in due fasi e svolgendo le attività sopra menzionate nella prima fase.
Questa prima fase è indipendente dall’ambiente e può essere eseguita anche in un ambiente CI (quindi si potrebbe utilizzare un’immagine quasi identica negli ambienti di staging e produzione, evitando possibili errori dovuti a ricostruzioni in date diverse, per non parlare della riduzione dei tempi di inattività).
Le attività di migrazione del database e di assets:precompile dovrebbero comunque essere eseguite sulla macchina di destinazione. Nella maggior parte dei casi, la migrazione del database sarebbe veloce. D’altra parte, il compito assets:precompile rappresenta un problema perché è la fase che richiede più tempo. Credo che ciò sia dovuto al fatto che alcune risorse devono conoscere alcune informazioni ambientali definite nel database, come alcune regole CSS, per essere eseguite.
Sarebbe estremamente positivo se questo compito fosse suddiviso in due parti: nella prima, tutte le risorse che non dipendono dall’ambiente verrebbero elaborate e potrebbero essere eseguite in un ambiente CI; nella seconda fase, verrebbero compilate solo le risorse che dipendono da dati presenti nel database, ecc. Detto questo, non so quanto sia tecnicamente complesso implementare questa soluzione.
Ho discusso dell’avvio del contenitore dell’applicazione in due fasi nel seguente argomento:
Le modifiche che ho apportato riguardavano esclusivamente la suddivisione del modello web di Discourse in tre file, ma i compiti restano gli stessi. Tuttavia, sarebbe ottimo se il team di Discourse supportasse questa modalità, in modo da non dover aggiornare i file ogni volta che ci saranno cambiamenti futuri nel modello web.