I container Docker sono ambienti intenzionalmente isolati. Ogni container ha il proprio filesystem a cui non è possibile accedere direttamente da altri container o dal tuo host.
A volte i contenitori potrebbero dover condividere i dati. Sebbene dovresti puntare a che i contenitori siano autosufficienti, ci sono scenari in cui la condivisione dei dati è inevitabile. Questo potrebbe essere così un secondo contenitore può accedere a una cache combinata, utilizzare un database con supporto file, creare un backup o eseguire operazioni sui dati generati dagli utenti, come un contenitore di ottimizzatore di immagini che elabora le foto del profilo caricate tramite un contenitore di server Web separato .
In questa guida, esamineremo alcuni metodi per trasferire i dati tra i contenitori Docker. Daremo per scontato che tu abbia già configurato Docker e abbia familiarità con concetti fondamentali come contenitori, immagini, volumi e reti.
Utilizzo dei volumi per condividere una directory
I volumi sono di fatto il modo per impostare la condivisione dei dati. Sono filesystem indipendenti che memorizzano i propri dati al di fuori di ogni singolo contenitore. Il montaggio di un volume su un percorso del filesystem all'interno di un contenitore fornisce l'accesso in lettura e scrittura ai dati del volume.
I volumi possono essere collegati a più contenitori contemporaneamente. Ciò facilita la condivisione e la persistenza dei dati senza interruzioni gestite da Docker.
Crea un volume per iniziare:
docker volume create --name shared-data
Quindi crea i tuoi contenitori, montando il volume sul percorso del filesystem previsto da ciascuna immagine:
docker run -d -v shared-data:/data --name example example-image:latest docker run -d -v shared-data:/backup-source --name backup backup-image:latest
In questo esempio, il backup
container otterrà un accesso effettivo all'example
/data
del contenitore directory. Verrà montato come /backup-source
; le modifiche apportate da uno dei contenitori si rifletteranno nell'altro.
Contenitori ad avvio rapido con volumi corrispondenti
L'esempio sopra può essere semplificato usando docker run
--volumes-from
del comando bandiera. Ciò fornisce un meccanismo per montare automaticamente i volumi che sono già utilizzati da un container esistente:
docker run -d --volumes-from example --name backup backup-image:latest
Questa volta il backup
contenitore riceverà i shared-data
volume montato nel suo /data
directory. Il --volumes-from
flag richiama tutte le definizioni di volume allegate all'example
contenitore. È particolarmente ideale per i lavori di backup e altri contenitori di breve durata che fungono da componenti ausiliari del tuo servizio principale.
Miglioramento della sicurezza con supporti di sola lettura
I volumi sono sempre montati in modalità lettura-scrittura per impostazione predefinita. Tutti i tuoi container con accesso a un volume possono modificarne il contenuto, causando potenzialmente una perdita di dati involontaria.
È consigliabile montare i volumi condivisi in modalità di sola lettura quando non è previsto che un contenitore apporti modifiche. Nell'esempio sopra, il backup
container deve solo leggere il contenuto dei shared-data
volume. L'impostazione del montaggio in modalità di sola lettura rafforza questa aspettativa, impedendo a bug o binari dannosi nell'immagine di eliminare i dati utilizzati dall'example
contenitore.
docker run -d -v shared-data:/backup-source:ro --name backup backup-image:latest
Aggiunta di ro
come terzo parametro separato da due punti al -v
flag indica che il volume deve essere montato in modalità di sola lettura. Puoi anche scrivere readonly
invece di ro
come alternativa più esplicita.
Condivisione dei dati su una rete
È possibile utilizzare gli scambi di rete come approccio alternativo alla condivisione dei dati tramite i volumi del filesystem. L'unione di due container alla stessa rete Docker consente loro di comunicare senza problemi utilizzando nomi host assegnati automaticamente:
docker network create demo-network docker run -d --net demo-network --name first example-image:latest docker run -d --net demo-network --name second another-image:latest
Qui first
sarà in grado di eseguire il ping di second
e viceversa. I tuoi contenitori potrebbero eseguire un servizio API HTTP che consente loro di interagire con i dati degli altri.
Continuando l'esempio di backup, ora il tuo backup
container potrebbe effettuare una richiesta di rete a http://example:8080/backup-data
per acquisire i dati di cui eseguire il backup. L'example
container dovrebbe rispondere con un archivio contenente tutti i dati che devono essere archiviati. Il contenitore di backup ha quindi la responsabilità di mantenere l'archivio in una posizione di archiviazione adeguata.
Imporre che la condivisione dei dati avvenga su una rete spesso aiuta gli sforzi di disaccoppiamento. Ti ritrovi con interfacce chiaramente definite che non creano forti dipendenze tra i servizi. L'accesso ai dati può essere controllato in modo più preciso esponendo le API per ogni tipo di dati, invece di concedere a ogni container l'accesso totale a un volume.
È importante considerare la sicurezza se si utilizza questo approccio. Assicurati che tutte le API HTTP progettate per l'accesso interno da parte degli altri contenitori Docker non abbiano porte esposte sulla rete bridge dell'host Docker. Questo è il comportamento predefinito quando si utilizzano le opzioni di rete mostrate sopra; vincolare una porta con -p 8080:8080
consentirebbe l'accesso all'API di backup tramite le interfacce di rete del tuo host. Questo sarebbe un problema di sicurezza.
Riepilogo
I container Docker sono ambienti isolati che non possono accedere ai filesystem degli altri. Tuttavia, puoi condividere i dati creando un volume montato in tutti i contenitori partecipanti. L'utilizzo di una rete Docker condivisa è un'opzione alternativa che fornisce una maggiore separazione negli scenari in cui non sono necessarie interazioni dirette con il filesystem.
È buona norma limitare il più possibile le interazioni tra contenitori. I casi in cui è necessaria la condivisione dei dati dovrebbero essere chiaramente definiti per evitare di accoppiare strettamente i servizi tra loro. Contenitori che hanno una rigida dipendenza dai dati di un altro container può essere più complicato da implementare e mantenere nel tempo, erodendo i vantaggi più ampi della containerizzazione e dell'isolamento.