Docker ADD vs VOLUME


116

Sto imparando Docker e ho dubbi su quando e dove usare ADDe VOLUME. Ecco cosa penso che facciano entrambi:

INSERISCI

Copia i file nell'immagine al momento della creazione. L'immagine ha tutti i file in modo da poter distribuire molto facilmente. D'altra parte, la necessità di compilare ogni volta non sembra una buona idea in fase di sviluppo perché la compilazione richiede che lo sviluppatore esegua un comando per ricostruire il contenitore; inoltre, la costruzione del container può richiedere molto tempo.

VOLUME

Capisco che usando docker run -vpuoi montare una cartella host all'interno del tuo contenitore, in questo modo puoi modificare facilmente i file e guardare l'app nel tuo contenitore reagire alle modifiche. Sembra fantastico in fase di sviluppo, ma non sono sicuro di come distribuire i miei file in questo modo.


3
In generale, è meglio preferire COPYa ADD. Sono quasi uguali, ma ADDhanno alcune capacità extra rispetto agli URL e ai file di archivio che possono essere sorprendenti.
Adrian Mouat

2
@jamesmstone - quel link (e la documentazione docker ufficiale) consiglia il contrario - usa COPY piuttosto che ADD.
Software Engineer

oops, hai ragione - ciao!
jamesmstone

Risposte:


183

INSERISCI

La differenza fondamentale tra questi due è che ADDtutto ciò che stai aggiungendo, sia esso una cartella o solo un file, fa parte della tua immagine . Chiunque utilizzi l'immagine che hai costruito in seguito avrà accesso a qualunque cosa tu ADD. Questo è vero anche se in seguito lo rimuovi perché Docker funziona in livelli e il ADDlivello esisterà ancora come parte dell'immagine. Per essere chiari, hai solo ADDqualcosa in fase di costruzione e non puoi mai ADDin fase di esecuzione.

Alcuni esempi di casi in cui vorresti utilizzare ADD:

  • Hai alcuni requisiti in un file requirements.txt che desideri fare riferimento e installare nel tuo Dockerfile. Puoi quindi fare: ADD ./requirements.txt /requirements.txtseguito daRUN pip install -r /requirements.txt
  • Si desidera utilizzare il codice dell'app come contesto nel Dockerfile, ad esempio, se si desidera impostare la directory dell'app come directory di lavoro nell'immagine e fare in modo che il comando predefinito in un contenitore eseguito dall'immagine esegua effettivamente l'app, è necessario può fare:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

VOLUME

Il volume, d'altra parte, consente a un contenitore eseguito dalla tua immagine di accedere a un percorso su qualsiasi macchina locale su cui viene eseguito il contenitore. Non è possibile utilizzare i file dalla VOLUMEdirectory nel Dockerfile . Qualsiasi cosa nella directory del volume non sarà accessibile in fase di compilazione ma sarà accessibile in fase di esecuzione .

Alcuni esempi di casi in cui vorresti utilizzare VOLUME:

  • L'app in esecuzione nel tuo contenitore effettua l'accesso /var/log/my_app. Si desidera che quei log siano accessibili sulla macchina host e non vengano eliminati quando il contenitore viene rimosso. Puoi farlo creando un punto di montaggio in /var/log/my_appaggiungendo VOLUME /var/log/my_appal tuo Dockerfile e quindi eseguendo il tuo contenitore condocker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag
  • Hai alcuni file di impostazioni locali a cui vuoi che l'app nel contenitore abbia accesso. Forse quei file di impostazioni sono diversi sulla tua macchina locale rispetto a sviluppo e produzione. Soprattutto se quei file di impostazioni sono segreti, nel qual caso sicuramente non li vuoi nella tua immagine . Una buona strategia in questo caso è aggiungere VOLUME /etc/settings/my_app_settingsal Dockerfile, eseguire il contenitore con docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tage assicurarsi che / host / settings / dir esista in tutti gli ambienti in cui prevedi che la tua app venga eseguita.

13
Di gran lunga il post più utile che ho trovato finora su AGGIUNGI e VOLUME
Jasmeet

5
Cosa succede se VOLUME è specificato, ma non fornito durante il docker run (ad es. Manca il parametro -v xxx)? È il resp. Il VOLUME diventa quindi effettivamente transitorio?
col.panic

All'interno di un Dockerfile, i volumi sono probabilmente pensati solo per la persistenza e / o il debug, ma puoi utilizzare l'opzione della riga di comando del volume per inserire un'app in un'immagine esistente (non è necessario Dockerfile) ed eseguirla in questo modo docker run -v $HOST_PATH:$CONTAINER_PATH node:latest node $CONTAINER_PATH/app.js.
Chinoto Vokro

bel dettaglio "strato"
stratovarius

27

L' VOLUMEistruzione crea un volume di dati nel contenitore Docker in fase di runtime. La directory fornita come argomento VOLUMEè una directory che ignora il file system dell'Unione e viene utilizzata principalmente per i dati persistenti e condivisi.

Se esegui docker inspect <your-container>, vedrai sotto la Mountssezione che è presente una Sourceche rappresenta la posizione della directory sull'host e una Destinationche rappresenta la posizione della directory montata nel contenitore. Per esempio,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

Ecco 3 casi d'uso per docker run -v:

  1. docker run -v /data: Questo è analogo alla specifica VOLUMEdell'istruzione nel Dockerfile.
  2. docker run -v $host_path:$container_path: Questo ti permette di montare $host_pathdal tuo host al $container_pathtuo container durante il runtime. In fase di sviluppo, questo è utile per condividere il codice sorgente sul tuo host con il contenitore. In produzione, questo può essere usato per montare cose come le informazioni DNS dell'host (trovate in /etc/resolv.conf) o segreti nel contenitore. Al contrario, puoi anche utilizzare questa tecnica per scrivere i log del contenitore in cartelle specifiche sull'host. Entrambi $host_pathe $container_pathdevono essere percorsi assoluti.
  3. docker run -v my_volume:$container_path: Crea un volume di dati nel tuo contenitore in $container_pathe lo denomina my_volume. È essenzialmente lo stesso che creare e denominare un volume utilizzando docker volume create my_volume. Denominare un volume in questo modo è utile per un volume di dati contenitore e un volume di archiviazione condiviso utilizzando un driver di archiviazione multi-host come Flocker .

Si noti che l'approccio di montare una cartella host come volume di dati non è disponibile in Dockerfile. Per citare la documentazione di Docker ,

Nota: non è disponibile da un Dockerfile a causa della portabilità e dello scopo di condivisione di esso. Poiché la directory host è, per sua natura, dipendente dall'host, una directory host specificata in un Dockerfile probabilmente non funzionerebbe su tutti gli host.

Ora, se desideri copiare i tuoi file in contenitori in ambienti non di sviluppo, puoi utilizzare le istruzioni ADDo COPYnel Dockerfile. Questi sono ciò che di solito uso per la distribuzione senza sviluppo.


3
Devo creare 2 file Docker? Uno per lo sviluppo e uno per la distribuzione?
Cristian Garcia

Non credo proprio. Non c'è niente di sbagliato nell'avere l' ADDistruzione nel tuo Dockerfile, poiché viene eseguita solo dal docker buildcomando. Ciò è necessario quando altri creano il tuo contenitore per la prima volta e quando sei pronto per distribuirlo in altri ambienti non di sviluppo.
ivan.sim

3
Ma non sarebbe più efficiente creare un'immagine senza i file e utilizzare il -vcomando per lo sviluppo e fare in modo che un altro file Docker crei un'immagine che include i file con ADDper la distribuzione?
Cristian Garcia

1
È un compromesso che devi decidere. Scegli ciò che funziona per te. Quanto dura comunque la build con un ADD? Un paio di secondi in totale? Se hai due file Dockerfile e lo condividi con altri (o lo pubblichi nel registro Docker ), qual è il file predefinito? Avrai un sovraccarico di manutenzione extra per assicurarti che il Dockerfile predefinito giusto arrivi agli utenti giusti. Ma alla fine della giornata, decidi tu cosa funziona meglio per te. Personalmente, mi piace assicurarmi che ci sia uno e un solo Dockerfile per creare il mio contenitore.
ivan.sim

11
A proposito, penso che vada bene prima ADD, quindi sovrascrivere quell'aggiunta con -v per lo sviluppo. In questo modo non avrai bisogno di Dockerfile separati.
Attila Szeremi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.