Backup e aggiornamento di uno stack Docker Compose
Scopri cosa salvare: file Compose, .env, volumi e dump del database. Verifica il ripristino prima dell'upgrade e riduci i rischi delle migrazioni irreversibili.
Contenuto necessario per il backup di uno stack Docker Compose
Il backup di uno stack Docker Compose deve contenere quattro elementi distinti. Se ne manca anche uno solo, l'applicazione non può essere ripristinata: il file Compose, il file .env presente nella stessa directory, il contenuto di ogni volume e un dump del database creato con il client del database stesso. Copiare i file del database mentre il relativo container è in esecuzione non costituisce un backup. Gli aggiornamenti seguono lo stesso elenco e una regola aggiuntiva: eseguire il backup prima di effettuare il pull, perché le migrazioni dello schema sono progettate per procedere in avanti e la maggior parte dei progetti non offre una procedura di rollback.
Quanto segue presuppone che lo stack sia già stato distribuito e che docker compose ps ne mostri lo stato in esecuzione. Gli esempi usano una directory del progetto in /srv/myapp, con servizi denominati app e db. Sostituire questi nomi con quelli in uso nel proprio ambiente. I comandi restano volutamente generici, perché gli aspetti importanti, cioè i volumi e il database, funzionano allo stesso modo indipendentemente dall'applicazione.
Verifica cosa archivia realmente il tuo stack
cd /srv/myapp
docker compose ps
docker compose config --volumes
docker volume ls --filter label=com.docker.compose.project=myappdocker compose config --volumes stampa i nomi brevi dei volumi denominati dichiarati dal file. docker volume ls stampa i nomi effettivi con cui questi volumi sono presenti sul disco. I due elenchi differiscono perché Compose antepone il nome del progetto: un volume scritto come db_data nel file esiste come myapp_db_data. Per impostazione predefinita, il nome del progetto corrisponde al nome della directory. Se rinomini la directory, lo stack utilizza un nuovo insieme di volumi vuoti e lascia quelli precedenti con tutti i tuoi dati. Ogni comando riportato di seguito richiede il nome effettivo ottenuto da docker volume ls.
I bind mount non compaiono in nessuno dei due elenchi. Nel file Compose sono le voci che riportano un percorso dell'host a sinistra dei due punti, ./config:/app/config. Sono directory normali sull'host, quindi puoi accedervi con gli strumenti consueti. I volumi denominati si trovano in /var/lib/docker/volumes/ e docker volume inspect --format '{{.Mountpoint}}' myapp_db_data stampa il percorso esatto di uno di essi. Il tipo di storage usato dallo stack determina la procedura di copia; bind mount e volumi denominati descrive in dettaglio il compromesso tra le due soluzioni.
Ora dividi ciò che hai trovato in due gruppi. Alcuni volumi contengono dati di stato che nulla può ricreare: file caricati, chiavi generate, il database stesso e qualsiasi dato inserito dall'utente nell'applicazione. Altri contengono dati derivati, come miniature e indici di ricerca, che l'applicazione ricostruisce autonomamente. Eseguire il backup del secondo gruppo richiede spazio su disco e aumenta i tempi di ripristino, senza offrire alcun vantaggio. Un volume della cache Redis è l'esempio più chiaro: perderlo comporta soltanto una prima richiesta più lenta.
Eseguire il backup del file Compose e del file .env
Entrambi i file si trovano sull'host, nella stessa directory, e nessuno dei due è contenuto in un volume. Il .env contiene la password del database, il secret dell'applicazione e gli eventuali token API. È quindi il file che consente di trasformare nuovamente un insieme di volumi in un'applicazione funzionante. Normalmente è inoltre elencato in .gitignore. Di conseguenza, un piano basato sull'idea che «la configurazione è in git» esclude proprio l'unico file più importante. Conservare i secret in un file env è il modello corretto e impone di includere quel file anche nel backup.
sudo install -d -m 700 -o "$USER" -g "$(id -gn)" /srv/backups/myapp
cp -a compose.yaml .env /srv/backups/myapp/
chmod 600 /srv/backups/myapp/.envCopiare ogni file Compose utilizzato dallo stack, non soltanto il primo. Uno stack avviato con -f compose.yaml -f compose.prod.yaml richiede entrambi i file per essere ripristinato nello stesso modo. Come vengono uniti più file Compose determina quali valori arrivano effettivamente al container.
Un'avvertenza riguarda il rapporto tra .env e i volumi. L'immagine ufficiale Postgres legge POSTGRES_PASSWORD soltanto quando inizializza una directory dati vuota. La modifica successiva di quel valore non cambia la password nel database. Se si ripristina il volume del mese scorso insieme al .env di oggi, l'applicazione non riesce a connettersi con FATAL: password authentication failed for user "appuser", anche se entrambi i file sembrano corretti a un controllo visivo. Conservare insieme .env e i volumi relativi allo stesso momento nello stesso backup.
Eseguire il dump con il client del database
Un server di database scrive continuamente nei propri file. Un tar di /var/lib/postgresql/data eseguito mentre il server è in funzione copia alcune pagine precedenti a una scrittura e altre successive. L'archivio contiene quindi una combinazione di momenti diversi, che potrebbe non essere ripristinabile. Uno strumento di dump legge all'interno di una singola transazione. Il file contiene così un unico stato coerente. Questa differenza distingue un backup da una copia.
docker compose exec -T db sh -c \
'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
> /srv/backups/myapp/db-$(date +%F).dumpMantieni -T. Disabilita l'allocazione di TTY. Quando un TTY è collegato, Docker converte il flusso di output prima di inviarlo alla shell. Questo danneggia un dump binario. Te ne accorgerai soltanto quando il ripristino fallirà. Anche le virgolette singole sono importanti. Impediscono alla shell dell'host di espandere $POSTGRES_USER. In questo modo lo espande la shell all'interno del container, usando i valori già impostati dal file compose. -Fc scrive il formato custom. Questo formato comprime i dati durante la scrittura e consente a pg_restore di selezionare in seguito singoli oggetti.
I ruoli e le relative password risiedono al di fuori di ogni singolo database. Esegui quindi il dump anche di questi:
docker compose exec -T db sh -c 'pg_dumpall -U "$POSTGRES_USER" --globals-only' \
> /srv/backups/myapp/globals.sqlControlla quindi che il file sia un dump e non un messaggio di errore:
ls -lh /srv/backups/myapp/
head -c 5 /srv/backups/myapp/db-$(date +%F).dumpUn dump in formato custom inizia con i cinque byte PGDMP. Un file di dimensione zero, oppure un file che inizia con pg_dump:, indica che il comando è fallito. La shell crea il file di output prima di eseguire il comando. Un dump non riuscito lascia quindi comunque un file con un nome e una data plausibili. Questo è il più comune errore di backup silenzioso.
Per MariaDB o MySQL cambia il client, ma la struttura resta la stessa:
docker compose exec -T db sh -c \
'mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction --databases "$MARIADB_DATABASE"' \
> /srv/backups/myapp/db-$(date +%F).sql--single-transaction esegue un dump coerente delle tabelle InnoDB senza bloccare le scritture. Nell'immagine MySQL il comando è mysqldump e le variabili sono MYSQL_ROOT_PASSWORD e MYSQL_DATABASE. Nelle immagini MariaDB attuali mysqldump continua a funzionare come nome compatibile per mariadb-dump. Una password specificata nella riga di comando è visibile nell'elenco dei processi del container per tutta la durata del dump.
SQLite richiede alcune precauzioni specifiche. Il database è costituito da un solo file, ma le transazioni recenti possono trovarsi ancora in un file -wal separato accanto a quello principale. Copiando soltanto .db si ottiene quindi un database privo delle scritture più recenti. Se l'immagine include il client, sqlite3 /data/app.db ".backup '/data/app-backup.db'" scrive una copia coerente mentre l'applicazione è in esecuzione. In caso contrario, arresta il container e copia il file .db insieme ai file associati -wal e -shm.
Se il database è in esecuzione sull'host anziché all'interno dello stack, applica gli stessi comandi senza il prefisso docker compose exec. Prima del prossimo rebuild, consulta anche eseguire il database in Docker o sull'host.
Acquisire i volumi
Un volume denominato non ha un percorso dell'host da modificare manualmente. Montalo quindi in un container temporaneo e crea l'archivio da lì.
docker run --rm \
-v myapp_uploads:/data:ro \
-v /srv/backups/myapp:/backup \
alpine:3 tar czf /backup/uploads.tar.gz -C /data .Il container di supporto monta il volume in sola lettura in /data e la directory di backup in /backup, quindi scrive l'archivio sul lato host. --rm rimuove il container di supporto non appena tar termina. :ro è importante, perché un comando tar digitato in modo errato non può danneggiare la sorgente. -C /data . fa sì che il ripristino venga eseguito nel percorso corretto: memorizza ogni percorso in relazione alla radice del volume. Se scrivi invece tar czf /backup/uploads.tar.gz /data, ogni percorso riceve un data/ iniziale. Di conseguenza, il ripristino crea /data/data all'interno del volume e l'applicazione vede una directory vuota. L'archivio appartiene a root, perché tar è stato eseguito come root all'interno del container. Esegui sudo chown "$USER" /srv/backups/myapp/uploads.tar.gz se questo comportamento crea problemi e consulta come PUID e PGID determinano la proprietà dei file se i file ripristinati risultano illeggibili per l'applicazione.
Esegui il comando una volta per ogni volume denominato. I bind mount non richiedono alcun container: tar czf /srv/backups/myapp/config.tar.gz -C /srv/myapp/config . svolge la stessa funzione direttamente sull'host.
Decidi per ogni volume se l'applicazione deve essere arrestata. Un tar eseguito mentre l'applicazione riscrive il volume può acquisire un file durante una scrittura. Per una directory di upload, in cui i file vengono scritti una volta e poi soltanto letti, il rischio è ridotto. Per qualsiasi altro contenuto, arresta il servizio per tutta la durata della copia con docker compose stop app, quindi esegui docker compose start app. stop lascia intatti container e volumi, che è esattamente ciò che serve in questo caso. Prima di eseguire uno dei due comandi, verifica la differenza tra down e stop.
Non considerare un tar del volume del database come il backup del database. Il backup è il dump. Un archivio del volume di un database arrestato è soltanto un metodo utile per una ricostruzione rapida.
Ordine delle operazioni
- Copiare i file Compose e
.envnella directory di backup. - Eseguire il dump del database mentre è ancora in esecuzione.
- Arrestare il container dell’applicazione se i relativi volumi vengono modificati direttamente.
- Archiviare ogni volume denominato e ogni directory usata come bind mount.
- Riavviare ciò che è stato arrestato, quindi verificare con
docker compose ps. - Annotare i tag e i digest delle immagini utilizzate dallo stack.
- Copiare l’intera directory di backup su un altro server.
Il passaggio 7 è quello che spesso viene rimandato.
Porta la copia fuori dal server
Un backup sullo stesso disco dello stack protegge solo dagli errori dell’operatore. Non protegge da altro. Un volume guasto, un server eliminato o un account perso compromettono entrambe le copie nello stesso momento. Invia la directory a uno storage che non appartenga a questo VPS, secondo una pianificazione e con una policy di conservazione. La guida backup restic da un VPS illustra la configurazione del repository, i flag di conservazione e il comando di verifica, quindi non è necessario ripetere questi passaggi.
restic può anche leggere il dump direttamente da una pipe. In questo modo il database in chiaro non viene mai scritto sul disco:
docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
| restic backup --stdin --stdin-filename db.dumpQualunque strumento utilizzi, configura la pianificazione in un timer systemd o in un cron job e fai in modo che il job segnali gli errori in un punto che controllerai. Uno script di backup il cui output non viene raccolto può smettere di funzionare per sei mesi senza che nessuno se ne accorga.
Verificare il funzionamento del backup con un'esercitazione di ripristino
Un backup che nessuno ha mai ripristinato è soltanto un'ipotesi. L'esercitazione seguente ripristina i dati in un secondo stack eseguito accanto al primo, così la produzione continua a fornire il servizio e nessun comando eseguito può raggiungerla.
Il meccanismo si basa sul nome del progetto. Compose lo ricava dal nome della directory e lo applica a ogni container e volume che crea. Copia il backup in una nuova directory: lo stack ripristinato otterrà automaticamente volumi propri.
sudo install -d -m 700 -o "$USER" -g "$(id -gn)" /srv/myapp-restore
cd /srv/myapp-restore
cp /srv/backups/myapp/compose.yaml /srv/backups/myapp/.env .Modifica il file Compose copiato in modo che la porta pubblicata sull'host non entri in conflitto con lo stack in esecuzione: sostituisci 18080:8080 a 8080:8080 oppure modifica la variabile che la definisce nel file .env copiato. Quindi crea i container e i relativi volumi vuoti senza avviare nulla:
docker compose create
docker volume ls --filter label=com.docker.compose.project=myapp-restoreIl secondo comando dovrebbe elencare gli stessi nomi di volume usati dalla produzione, preceduti da myapp-restore_. Riempili, avvia autonomamente il database e carica il dump:
docker run --rm -v myapp-restore_uploads:/data -v /srv/backups/myapp:/backup \
alpine:3 tar xzf /backup/uploads.tar.gz -C /data
docker compose up -d db
docker compose exec -T db sh -c \
'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists' \
< /srv/backups/myapp/db-2026-08-16.dump--clean --if-exists elimina ogni oggetto prima di ricrearlo, rendendo il ripristino ripetibile. Senza questa opzione, una seconda esecuzione su un database che contiene già quelle tabelle si interrompe con pg_restore: error: could not execute query: ERROR: relation "users" already exists.
Quindi avvia il resto dello stack e verifica il funzionamento come farebbe un utente:
docker compose up -d --wait
docker compose exec -T db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt"'
docker compose logs --tail=50docker compose up -d --wait attende finché ogni servizio risulta in esecuzione o in stato healthy e restituisce un codice diverso da zero se uno di essi non raggiunge mai questo stato. Per questo il passaggio può essere incluso in uno script. Se un servizio non raggiunge mai lo stato healthy, docker compose ps ne mostra lo stato. I controlli di integrità di Compose spiega il significato dei valori mostrati in quella colonna. Quindi apri l'applicazione sulla porta alternativa ed esegui l'accesso con un account reale. Crea un record e apri un file memorizzato in un volume. Questa coppia di verifiche dimostra che il dump è stato ripristinato, che il volume è stato ripristinato e che i due contenuti sono coerenti. Un'esercitazione che verifica soltanto la visualizzazione della pagina di accesso non dimostra nulla sui dati.
Al termine dell'esercitazione, rimuovi lo stack:
docker compose down -vQuesto è l'unico caso in cui -v è l'opzione corretta. Nella directory di produzione, lo stesso comando elimina i volumi che stai cercando di proteggere.
Come aggiornare uno stack Compose
Leggere le note di rilascio per ogni versione compresa tra quella attualmente in esecuzione e quella desiderata, quindi cercare i termini breaking e migration. I progetti che non supportano il salto tra diverse versioni principali lo indicano in questa documentazione. Una migrazione che non riesce a essere eseguita lo comunica soltanto dopo avere già modificato parte dello schema.
Registrare lo stato attuale prima di modificare qualsiasi cosa:
docker compose images
docker image inspect --format '{{index .RepoDigests 0}}' postgres:16.4docker compose images elenca l'immagine e il tag utilizzati in questo momento da ogni servizio. Il digest è l'unico valore che identifica esattamente un'immagine, perché un tag può essere spostato in qualsiasi momento per puntare a un'immagine diversa.
Creare il backup indicato nelle sezioni precedenti e copiarlo fuori dal server. Farlo anche per una patch release. Gli aggiornamenti semplici sono quelli per cui si tende a non preparare un backup.
Impostare quindi la versione nel file Compose, perché latest non è una versione:
services:
db:
image: postgres:16.4Con image: postgres:latest, docker compose pull scarica ciò a cui punta oggi quel tag, e non è possibile identificare ciò che era in esecuzione ieri. Un tag bloccato trasforma l'aggiornamento in una modifica di una sola riga, leggibile in git diff e reversibile con un'ulteriore modifica. Bloccare nello stesso modo l'immagine dell'applicazione, usando la versione esatta indicata nella pagina delle release del progetto.
Scaricare le immagini e ricreare i container:
docker compose pull
docker compose up -d --waitdocker compose up -d confronta il file con i container in esecuzione e ricrea soltanto i servizi la cui immagine o configurazione è cambiata. Non modifica i volumi denominati, quindi il nuovo container viene avviato sui dati esistenti. Questo è l'obiettivo dell'operazione, ma anche il rischio: la prima esecuzione della nuova versione è solitamente il momento in cui viene eseguita la migrazione dello schema.
Controllare l'avanzamento:
docker compose ps
docker compose logs -f --tail=100 appUn container non riuscito mostra Exited (1) nella colonna STATUS di docker compose ps, mentre il motivo è riportato nelle ultime righe del log. Gli errori di migrazione sono visibili nei log e non sono rilevabili altrove. Quando i log si stabilizzano, accedere all'applicazione e utilizzarla per un minuto.
Se docker compose pull si interrompe con no space left on device, la causa più comune sono i vecchi layer delle immagini. Il comando eliminare le immagini Docker non utilizzate recupera lo spazio. Eseguire la pulizia dopo avere verificato che l'aggiornamento funzioni, non prima, perché il rollback rapido utilizza proprio quei vecchi layer.
Come eseguire il rollback quando l’upgrade non va a buon fine
Esistono due casi, con costi operativi molto diversi. Se la nuova versione non ha modificato lo schema, il rollback richiede una sola riga: ripristinare il vecchio tag nel file Compose ed eseguire docker compose up -d. Il container viene sostituito, i volumi restano invariati e il vecchio codice legge i dati che aveva scritto.
Se la nuova versione ha eseguito una migrazione dello schema, il vecchio codice non può più leggerlo. Le migrazioni sono progettate per procedere in avanti e la maggior parte dei progetti non include alcuno script di downgrade. Di conseguenza, la vecchia versione si avvia, ma fallisce alla prima query su una colonna rinominata o eliminata, con errori del tipo ERROR: column "avatar_url" does not exist. Per tornare indietro serve il dump creato prima del pull: ripristinare il vecchio tag, rimuovere il volume del database, ricrearlo vuoto, ripristinare il dump e avviare il servizio. Senza quel dump non esiste alcun modo per tornare indietro. È proprio questo il motivo per cui il backup deve precedere il pull.
Le major version di Postgres rappresentano il caso più critico. Spesso sorprendono perché l’errore si verifica durante l’upgrade, non durante il rollback. Il formato su disco cambia a ogni major release. Modificare postgres:16.4 in postgres:17.2, eseguire docker compose up -d e il nuovo server rifiuta di avviarsi:
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2.L’immagine non esegue pg_upgrade automaticamente. In uno stack Compose, la procedura supportata è dump, sostituzione e ripristino: creare il dump mentre la vecchia versione è ancora in esecuzione, docker compose down, rimuovere il volume del database, impostare il nuovo tag, eseguire docker compose create per creare una nuova directory dati vuota, avviare il database, ripristinare il dump e avviare il resto dello stack. Conservare il vecchio dump finché la nuova major non avrà gestito traffico reale per un giorno. Gli upgrade minor all’interno della stessa major, ad esempio da 16.4 a 16.9, non richiedono questa procedura, perché il formato resta stabile e il container si avvia normalmente.
Gli snapshot dei VPS sono un backup?
Sono un complemento al backup e i due strumenti presentano modalità di errore diverse. Uno snapshot copia l’intero disco a livello di hypervisor, quindi ripristina l’intera macchina in pochi minuti, inclusi i dati che non avevi incluso nel backup. È quindi lo strumento adatto a un caso specifico: l’aggiornamento ha danneggiato il server e vuoi riportarlo allo stato di venti minuti prima.
Per tutto il resto, è uno strumento poco adatto. La granularità corrisponde all’intera macchina, quindi per recuperare una singola tabella eliminata devi ripristinare un intero server da qualche parte e quindi estrarre la tabella. La conservazione è in genere breve. Le copie risiedono normalmente nello stesso account del provider in cui si trova il server, quindi la perdita dell’account comporta la perdita simultanea del server e dei relativi snapshot. Inoltre, uno snapshot di una macchina in esecuzione acquisisce il database durante una scrittura, quindi al primo avvio il database esegue il crash recovery e qualsiasi transazione ancora in corso va persa.
Usa entrambi. Lo snapshot è il pulsante di annullamento per la finestra di aggiornamento. Il dump è la copia che resta disponibile anche se l’account viene eliminato. come differiscono snapshot e backup analizza quali errori copre effettivamente ciascuno strumento. La stessa directory di backup serve anche per trasformare spostare uno stack su un nuovo VPS in un’attività ordinaria, invece di dover ricostruire tutto sulla base dei ricordi.
Cosa non funziona e cosa vedrai
Il flag dei volumi con down. docker compose down -v rimuove i volumi denominati dichiarati dal file e Compose lo conferma con una riga contenente Volume myapp_db_data Removed. Non è possibile annullare l'operazione. Il semplice docker compose down li lascia invariati. Digita la forma estesa, docker compose down --volumes, in modo che il flag distruttivo debba essere scritto per esteso.
Un dump senza la stringa magica. pg_restore: error: did not find magic string in file header indica che il file non è un archivio. La causa più comune è l'assenza di -T su docker compose exec, perché con un TTY collegato il flusso viene tradotto mentre raggiunge la shell e il dump binario si danneggia. Crea di nuovo il dump con -T, quindi controlla i primi cinque byte con head -c 5.
Una password che non cambia. FATAL: password authentication failed for user "appuser" dopo un ripristino indica che .env e la directory dei dati provengono da momenti diversi. L'immagine imposta la password soltanto quando crea una directory dei dati vuota, quindi modificare in seguito .env non cambia nulla all'interno del database. Ripristina il .env corrispondente oppure modifica la password nel database con ALTER USER.
Un secondo volume vuoto. Docker crea un volume su richiesta, quindi docker run -v myapp_upload:/data con s mancante scrive in un nuovo volume vuoto e segnala il successo. docker volume ls mostra quindi entrambi i nomi, uno dei quali non contiene dati. Copia i nomi dei volumi da docker volume ls invece di inserirli a memoria.
Un ripristino eseguito in produzione. Eseguire i comandi di ripristino in /srv/myapp invece che in /srv/myapp-restore sovrascrive i dati attivi con il backup; i comandi sono identici in entrambi i contesti. Controlla pwd prima di ogni comando di ripristino e mantieni l'esercitazione nella sua directory dedicata.
FAQ
docker compose down elimina i miei dati?
No. docker compose down rimuove i container e la rete predefinita, ma lascia invariati i volumi denominati e i bind mount. docker compose down -v rimuove i volumi denominati dichiarati dal file e l'operazione è permanente. I bind mount sono directory dell'host, quindi Compose non li rimuove. Se vuoi arrestare i servizi durante un backup lasciando invariato tutto il resto, usa invece docker compose stop.
Posso copiare la directory dei dati di Postgres invece di eseguire pg_dump?
Solo con il container arrestato. Mentre il server è in esecuzione, i file cambiano e la copia può contenere dati appartenenti a momenti diversi, senza uno stato coerente da ripristinare. Una copia a livello di file è inoltre vincolata a una specifica major version di Postgres, quindi non si avvierà con una versione diversa. Arresta il container, archivia il volume, avvialo di nuovo e considera il risultato un metodo rapido per ricostruire l'ambiente, non l'unico backup disponibile. Il dump è la copia portabile ed è quella da cui eseguire il ripristino.
Come aggiorno Postgres a una nuova major version in Compose?
Cambiare il tag non basta. Il nuovo server rifiuta di avviarsi sulla vecchia directory dei dati e registra The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2. Esegui pg_dump mentre la versione precedente è ancora in esecuzione, quindi docker compose down, rimuovi il volume del database, imposta il nuovo tag, esegui docker compose create per creare un volume vuoto, avvia il database e ripristina il dump al suo interno. Conserva il vecchio dump finché la nuova versione non ha gestito traffico reale.
Con quale frequenza devo eseguire i backup e per quanto tempo devo conservarli?
Imposta l'intervallo in base alla quantità di lavoro che sei disposto a ripetere. Un backup notturno è adatto a uno stack personale o di un piccolo team; aggiungi un backup manuale subito prima di ogni aggiornamento. Per la conservazione, mantieni una cronologia sufficiente a coprire i danni che potresti non rilevare immediatamente: una tabella danneggiata scoperta venerdì non viene recuperata dalla copia di giovedì notte. restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune è un criterio iniziale ragionevole. Qualunque sia la pianificazione, esegui un ripristino una volta a trimestre. Finché non lo hai fatto, non hai backup: hai solo file.
Devo arrestare l'intero stack per eseguire un backup?
Di solito no. Il dump del database è coerente mentre il server è in esecuzione, quindi il database non richiede downtime. Il punto critico sono i volumi. Se l'applicazione aggiunge soltanto file, ad esempio in una directory per gli upload, un'archiviazione a caldo è sufficientemente sicura. Se invece riscrive i file sul posto, arresta quel singolo servizio per la durata della copia con docker compose stop app e riavvialo al termine. Arrestare l'applicazione mentre il database continua a funzionare è normalmente la finestra sicura più breve che puoi ottenere.