Come posso aggiungere un volume a un contenitore Docker esistente?


297

Ho un contenitore Docker che ho creato semplicemente installando Docker su Ubuntu e facendo:

sudo docker run -i -t ubuntu /bin/bash

Ho immediatamente iniziato a installare Java e alcuni altri strumenti, ho trascorso un po 'di tempo con esso e ho fermato il contenitore

exit

Quindi ho voluto aggiungere un volume e ho capito che non era così semplice come pensavo. Se lo uso, sudo docker -v /somedir run ...finisco con un nuovo contenitore nuovo, quindi avrei installato Java e fatto quello che ho già fatto prima di arrivare a un contenitore con un volume montato.

Tutta la documentazione sul montaggio di una cartella dall'host sembra implicare che il montaggio di un volume è qualcosa che può essere fatto durante la creazione di un contenitore. Quindi l'unica opzione che devo evitare per riconfigurare un nuovo contenitore da zero è di impegnare il contenitore esistente in un repository e usarlo come base di uno nuovo durante il montaggio del volume.

È davvero l'unico modo per aggiungere un volume a un contenitore esistente?


1
Dopo i Container, questi sono diventati parte integrante dei Programmatori e quindi tali domande vengono poste più spesso qui. Domande inviate qui utilizzando dockertag sono 34k + , che sono molto più di quelli di due siti stackoverflow.com/questions/tagged/docker
MA Hossain Tonu

Risposte:


394

È possibile eseguire il commit del contenitore esistente (ovvero creare una nuova immagine dalle modifiche del contenitore) e quindi eseguirlo con i nuovi montaggi.

Esempio:

$ docker ps  -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                          PORTS               NAMES
    5a8f89adeead        ubuntu:14.04          "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       agitated_newton

$ docker commit 5a8f89adeead newimagename

$ docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash

Se va tutto bene, ferma il tuo vecchio contenitore e usa questo nuovo.

Questo è tutto :)


22
E se hai bisogno del nuovo contenitore per prendere il vecchio nome per qualche motivo, usa la ridenominazione della finestra mobile dopo aver rimosso quello vecchio.
Dirk,

10
volevo solo sottolineare che sopra dove dici newnameofcontainerche questo dovrebbe probabilmente essere chiamato new_image_name- perché docker commitcrea una nuova immagine sul tuo sistema. Di seguito, quando lo fai, docker runusi effettivamente il nome dell'immagine da cui vuoi eseguire un nuovo contenitore. Quanto sopra funziona, ma volevo solo chiarire per gli altri che il segnaposto soprannome di contenitore sopra è in realtà il nome di una nuova immagine. Grazie! risposta fantastica. oh, puoi vedere l'immagine appena creata dal primo comando di commit della finestra mobile usandodocker image ls
FireDragon

3
In effetti, non è necessario eseguire il commit di un nuovo contenitore se si desidera iniziare da un'immagine. Va docker run -v /srv/a:/tmp ubuntu:14.04bene.
YongHao Hu,

Ho già un contenitore in esecuzione con tutti i file. se il metodo di cui sopra crea un nuovo contenitore, non posso costruire tutto da capo ancora. C'è un modo per evitarlo e montarlo senza dover creare un nuovo contenitore o un'immagine?
dhinar,

Ciò manterrà i vecchi mapping dei volumi dal vecchio contenitore o dovrei ri-dichiararli anche con il nuovo contenitore?
thebeancounter,

79

Non abbiamo modo di aggiungere volume nel container in esecuzione, ma per raggiungere questo obiettivo puoi usare i comandi seguenti:

Copia file / cartelle tra un contenitore e il filesystem locale: -

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Per riferimento vedi:

https://docs.docker.com/engine/reference/commandline/cp/


47
C'è un'enorme differenza tra montare un volume e copiare file da e verso un contenitore ...
Jules,

31
Comunque mi ha aiutato. Non conoscevo il comando 'docker cp' e stavo cercando di ottenere esattamente questo: copiare i file dal contenitore in esecuzione all'host.
Ivan,

3
non è un mount, ma è utile per ripristinare i file tra contenitore e host locale.
linehrr

Sebbene ciò risolva il problema di replicare localmente i contenuti del contenitore, ciò non equivale ad essere equivalente al montaggio di un volume e non dovrebbe essere considerato un'alternativa. Vale a dire, la replica deve essere gestita dall'utente e i dati esistono ora in due posizioni.
Sebastian Gaweda,

1
Non capisco perché così tanti voti positivi, questa è una risposta molto sbagliata per la domanda posta.
João Matos,

33

Ho montato correttamente la /home/<user-name>cartella del mio host nella /mntcartella del contenitore esistente (non in esecuzione). Puoi farlo nel modo seguente:

  1. Apri il file di configurazione corrispondente al contenitore arrestato, che puoi trovare in /var/lib/docker/containers/99d...1fb/config.v2.json(potrebbe essere config.jsonper le versioni precedenti della finestra mobile).

  2. Trova MountPointssezione, che era vuoto nel mio caso: "MountPoints":{}. Quindi sostituire i contenuti con qualcosa del genere (è possibile copiare i contenuti corretti da un altro contenitore con le impostazioni appropriate):

"MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}

o lo stesso (formattato):

  "MountPoints": {
    "/mnt": {
      "Source": "/home/<user-name>",
      "Destination": "/mnt",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/home/<user-name>",
        "Target": "/mnt"
      },
      "SkipMountpointCreation": false
    }
  }
  1. Riavvia il servizio docker: service docker restart

Questo funziona per me con Ubuntu 18.04.1 e Docker 18.09.0


3
Grazie per la risposta. Il passaggio 3 è cruciale. Vorrei anche aggiungere che è meglio fermare il contenitore della finestra mobile prima di fare la scrittura.
Buzypi,

7
Questa è la risposta migliore in quanto preserva totalmente il contenitore esistente. Questo è quello che ho fatto: 1. Arrestare il motore docker: systemctl stop docker.service2. Modifica config.v2.json: vim <(jq . /var/lib/docker/containers/<container-ID>/config.v2.json)3. Salva gli aggiornamenti in un file: :w config.v2.json4. Esci da vim: :q!5. Aggiorna il file esistente: jq -c . config.v2.json > /var/lib/docker/containers/<container-ID>/config.v2.json6. Avvia il motore docker: systemctl start docker.service7. Avvia il contenitore se necessario : docker start <container-name/ID>8. Divertiti :-)
Controllo Android

2
Un passaggio chiave è service docker restart. Ho provato a docker restart <container>fare in modo che la nuova configurazione non sia stata prelevata e venga sovrascritta dalla vecchia configurazione.
KFL

1
Inoltre jqaiuterà abbastanza stampare il JSON quindi è modificabile mroe umana:cat config.v2.json | jq . > config.json
KFL

14

Jérôme Petazzoni ha un post sul blog piuttosto interessante su come allegare un volume a un container mentre è in esecuzione . Questo non è qualcosa che è integrato in Docker per impostazione predefinita, ma è possibile farlo.

Come sottolinea anche

Questo non funzionerà su filesystem che non sono basati su dispositivi a blocchi.

Funzionerà solo se / proc / mounts elenca correttamente il nodo del dispositivo a blocchi (che, come abbiamo visto sopra, non è necessariamente vero).

Inoltre, l'ho provato solo sul mio ambiente locale; Non ho nemmeno provato un'istanza cloud o qualcosa del genere

YMMV


8

Sfortunatamente l'opzione switch per montare un volume si trova solo nel runcomando.

docker run --help

-v, --volume list Bind mount a volume (default [])

Esiste un modo per aggirare questo problema, quindi non dovrai reinstallare le applicazioni che hai già impostato sul tuo contenitore.

  1. Esporta il tuo contenitore docker container export -o ./myimage.docker mycontainer
  2. Importa come immagine docker import ./myimage.docker myimage
  3. Poi docker run -i -t -v /somedir --name mycontainer myimage /bin/bash

1
Cordiali saluti - docker containernon è un comando valido su 1.11.2 (che è l'ultima versione supportata da Synology al momento della stesura). Non riesco a trovare alcun documento che dica quando è stato aggiunto, però. In questo caso il primo comando è docker export -o ./myimage.docker mycontainer.
Chris R. Donnelly,

2

Una nota per l'utilizzo dei contenitori Docker Windows dopo aver dovuto cercare questo problema per molto tempo!

condiditions:

  • Windows 10
  • Docker Desktop (ultima versione)
  • utilizzando Docker Windows Container per l'immagine microsoft / mssql-server-windows-developer

Problema:

  • Volevo montare un dizionario host nel mio contenitore di Windows.

Soluzione parzialmente discripta qui:

  • creare un contenitore finestra mobile

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

  • vai al comando shell nel contenitore

docker exec -it <CONTAINERID> cmd.exe

  • creare DIR

mkdir DirForMount

  • fermare il contenitore

docker container stop <CONTAINERID>

  • contenitore di commit

docker commit <CONTAINERID> <NEWIMAGENAME>

  • elimina il vecchio contenitore

docker container rm <CONTAINERID>

  • creare un nuovo contenitore con nuova immagine e volume di montaggio

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>

Dopo questo ho risolto questo problema sui contenitori delle finestre mobili.


-3

Il modo migliore è copiare tutti i file e le cartelle all'interno di una directory sul tuo file system locale: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH

SRC_PATHè sul contenitore DEST_PATHè su localhost

Quindi docker-compose downcollegare un volume allo stesso DEST_PATHed eseguire i contenitori Docker utilizzandodocker-compose up -d

Aggiungi volume seguendo in docker-compose.yml

volumes:
 - DEST_PATH:SRC_PATH

Ci sono altre opzioni migliori sopra.
MrR,

In effetti, ci sono opzioni migliori sopra e la copia dei file non li sta montando. Inoltre, la definizione di "volumi" fornita per l'opzione componi finestra mobile è il contrario: volumi: - HOST_PATH: CONTAINER_PATH
Guillaume S.
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.