Volumi Docker: guida alla persistenza dei dati dei container
Se sei alle prime armi con Docker, ti consigliamo di partire dalla nostra introduzione a Docker su Linux, dove abbiamo visto cosa sono immagini e container e come utilizzare i primi comandi.
Se invece hai già esperienza con i container… partiamo!
Dati persistenti e container: perché i volumi sono importanti
Uno dei concetti più interessanti di Docker è anche uno dei primi problemi che si incontrano quando si passa dai semplici test a un utilizzo reale dei container.
Un container può essere creato, avviato, fermato e infine eliminato. Ma cosa succede ai dati che abbiamo creato all’interno del container?
Immaginiamo, ad esempio, di avviare un database in Docker.
Il database contiene:
- configurazioni;
- utenti;
- tabelle;
- documenti;
- dati dell’applicazione.
Se tutti questi dati vengono memorizzati esclusivamente all’interno del filesystem scrivibile del container, eliminando il container rischiamo di perdere anche i dati.
È proprio qui che entrano in gioco i volumi Docker.
Un volume permette di separare il ciclo di vita dei dati da quello del container che li utilizza.
In altre parole:
Il container può essere eliminato e ricreato, mentre i dati rimangono disponibili.
È uno dei passaggi fondamentali per iniziare a utilizzare Docker non soltanto per fare prove, ma anche per eseguire servizi persistenti.
Cosa succede ai dati dentro un container?
Per capire perché esistono i volumi, dobbiamo prima capire come Docker gestisce il filesystem di un container.
Quando Docker avvia un container, parte dall’immagine utilizzata per crearlo. L’immagine contiene i filesystem layer necessari all’applicazione, mentre il container dispone anche di un proprio writable layer, cioè un livello scrivibile associato a quel particolare container.
Possiamo immaginarlo in questo modo:
IMMAGINE DOCKER
┌──────────────────┐
│ filesystem │
│ applicazione │
│ librerie │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Writable layer │
│ del container │
└──────────────────┘
│
▼
CONTAINER
Quando un’applicazione scrive un file, normalmente quel file finisce nel writable layer del container.
Il problema è che questo livello è legato al container.
Se il container viene eliminato, anche quel livello viene eliminato.
Docker stessa evidenzia proprio questa caratteristica: i dati scritti nel writable layer non sono pensati per sopravvivere alla distruzione del container.
Facciamo una prova pratica
Possiamo vedere il comportamento direttamente.
Creiamo un semplice container:
docker run -it --name test-dati ubuntu:24.04 bash
Una volta entrati nel container creiamo un file denominato dati.txt al suo interno, con una frase salvata come contenuto:
echo "Questo dato è dentro il container" > /dati.txt
Potremo quindi verificare con questo comando:
cat /dati.txt
che il file esiste, se otterremo la frase inserita con echo.
Se ora usciamo lanciando il comando “exit”, il container non sarà più in esecuzione ma esisterà ancora; potremo verificare questo tramite il seguente comando:
docker ps
e riavviandolo con:
docker start -ai test-dati
noteremo che il file sarà ancora presente nel container! Questo è normale: fermare un container non significa eliminarlo.
Ma lanciando il seguente comando:
docker rm test-dati
a questo punto il container non esisterà più fisicamente.
Se, quindi, ricreiamo il container:
docker run -it --name test-dati ubuntu:24.04 bash
e proviamo a lanciare le seguenti operazioni in sequenza:
cat /dati.txt
otterremo come risposta: “cat: /dati.txt: No such file or directory”!
Ovviamente il dato è scomparso perché era contenuto nel filesystem del vecchio container e disponibile nel nuovo container, perché era contenuto nel filesystem scrivibile del vecchio container, che è stato eliminato insieme al container.
Per evitare tuttavia queste situazioni fortunatamente ci danno una mano i volumi Docker!
Che cos’è un volume Docker?
Un volume è uno spazio di archiviazione gestito direttamente da Docker e separato dal filesystem del container.
Possiamo immaginarlo così:
HOST LINUX
│
┌─────────────┴─────────────┐
│ │
▼ ▼
CONTAINER VOLUME
┌───────────────┐ ┌───────────────┐
│ Applicazione │ │ Dati │
│ │◄────────►│ persistenti │
│ /app/data │ │ │
└───────────────┘ └───────────────┘
Il container vede il volume semplicemente come una directory.
Ad esempio /data: per l’applicazione quella directory appare come una normale cartella del filesystem del container, ma i dati vengono conservati nel volume gestito da Docker
La caratteristica fondamentale è che il volume non viene eliminato automaticamente insieme al container.
Il suo ciclo di vita è indipendente da quello del container.
Creare il primo volume
Creare un volume è molto semplice:
docker volume create dati-app
Possiamo verificare che esista con:
docker volume ls
Dovremmo vedere qualcosa come:
DRIVER VOLUME NAME
local dati-app
Docker mostrerà informazioni relative al volume, compreso il driver utilizzato e il percorso gestito dal Docker Engine.
È importante però una cosa:
Non è necessario entrare manualmente nella directory interna del volume sul filesystem dell’host.
Docker gestisce quella posizione e la documentazione raccomanda di interagire con i dati del volume attraverso il volume stesso e i container che lo montano, anziché manipolarne direttamente i file sul filesystem dell’host.
Utilizzare un volume con un container
Ora possiamo utilizzare il volume appena creato.
Creiamo un container Ubuntu:
docker run -it \
--name test-volume \
--mount type=volume,src=dati-app,dst=/data \
ubuntu:24.04 \
bash
All’interno del container possiamo controllare:
ls /data
Inizialmente la directory sarà vuota. Creiamo un file:
echo "Dato persistente" > /data/messaggio.txt
e verifichiamo:
cat /data/messaggio.txt
Dovremmo ottenere: “Dato persistente” come output!
Usciamo quindi con il comando “exit” e rimuoviamo il container:
docker rm test-volume
Il container è stato eliminato, il volume invece esiste ancora. Possiamo verificarlo così:
docker volume ls
e troveremo:
local dati-app
Prova del 9: ricreare il container e ritrovare i dati
Creiamo un nuovo container utilizzando lo stesso volume:
docker run -it \
--name test-volume-2 \
--mount type=volume,src=dati-app,dst=/data \
ubuntu:24.04 \
bash
Ora:
cat /data/messaggio.txt
restituirà:
Dato persistente
Abbiamo appena dimostrato il principio fondamentale dei volumi:
CONTAINER 1
│
│ scrive
▼
┌──────────────┐
│ dati-app │
└──────────────┘
▲
│ legge
│
CONTAINER 2
Il primo container è stato eliminato ma il volume no; il secondo container ha quindi potuto ritrovare gli stessi dati.
Conclusioni
I container Docker sono progettati per essere facilmente creati, fermati, sostituiti e ricreati.
Questa caratteristica è uno dei loro punti di forza, ma introduce una domanda fondamentale:
Dove mettiamo i dati che devono sopravvivere al container?
La risposta, nella maggior parte dei casi, è un volume Docker.
LICENZA E CONDIZIONI D’USO
Questo How-to è rilasciato sotto licenza Creative Commons Attribution-NonCommercial 3.0 Italy.
CONTATTI DELL’AUTORE
Marco Ciammella marco@orvietolinux.it
Orvieto Linux User Group info@orvietolinux.it