Copia dei file dall'host al contenitore Docker


1581

Sto cercando di creare una soluzione di backup e ripristino per i contenitori Docker con cui lavoriamo.

Ho un'immagine base Docker che ho creato ubuntu:basee non voglio ricostruirla ogni volta con un file Docker per aggiungere file ad esso.

Voglio creare uno script che viene eseguito dal computer host e crea un nuovo contenitore usando l' ubuntu:baseimmagine Docker e quindi copia i file in quel contenitore.

Come posso copiare i file dall'host al contenitore?


12
Se non vuoi ricostruire, perché non " docker commit "? Questo salva la tua immagine.
Berend de Boer,

28
Solo un'osservazione su una nozione che nessuno ha affrontato: in generale, tratta i contenitori come "effimeri". Ci sono casi d'uso per copiare file in / da un container in esecuzione (test, prototipazione). Ma se ti trovi in ​​una posizione in cui non riesci a ricostruire ciò di cui hai bisogno usando Dockerfile e / o componi, allora potresti essere in una brutta posizione. In genere non si desidera eseguire il backup dei contenitori come se fossero oggetti SO o addirittura VM. In generale :-)
Scott Prive,

Risposte:


2674

Il cpcomando può essere utilizzato per copiare i file.

Un file specifico può essere copiato nel contenitore come:

docker cp foo.txt mycontainer:/foo.txt

Un file specifico può essere copiato dal contenitore come:

docker cp mycontainer:/foo.txt foo.txt

Per enfasi, mycontainerè un ID contenitore , non un ID immagine .

Più file contenuti nella cartella srcpossono essere copiati nella targetcartella usando:

docker cp src/. mycontainer:/target
docker cp mycontainer:/src/. target

Riferimento: documenti CLI Docker percp

Nelle versioni Docker precedenti alla 1.8 era possibile solo copiare file da un contenitore all'host. Non dall'host a un contenitore.


2
nota anche che questo può essere sull'host vm o sul sistema operativo principale e funziona da host a container o vm a host (o sistema operativo principale)
Adam Tuliper - MSFT

7
In un file Docker è possibile utilizzare la parola chiave ADD per aggiungere file durante il tempo di compilazione.
0x7d7b

4
@ h3nrik COPYpreferito rispetto aADD quando applicabile.
Franklin Yu,

10
usare docker cpper copiare dal contenitore all'host funziona bene, ma quando lo si usa per copiare i file dall'host al contenitore, nessun effetto ... qualcuno sa perché? versione docker: Docker versione 1.10.3, build cb079f6-
unsupported

2
Posso copiare più file usando la finestra mobile cp dall'host al contenitore?
Yogesh,

182
  1. Ottieni nome contenitore o ID contenitore breve:

    $ docker ps
    
  2. Ottieni l'ID contenitore completo:

    $ docker inspect -f   '{{.Id}}'  SHORT_CONTAINER_ID-or-CONTAINER_NAME
    
  3. Copia il file:

    $ sudo cp path-file-host /var/lib/docker/aufs/mnt/FULL_CONTAINER_ID/PATH-NEW-FILE
    

ESEMPIO:

$ docker ps

CONTAINER ID      IMAGE    COMMAND       CREATED      STATUS       PORTS        NAMES

d8e703d7e303   solidleon/ssh:latest      /usr/sbin/sshd -D                      cranky_pare

$ docker inspect -f   '{{.Id}}' cranky_pare

o

$ docker inspect -f   '{{.Id}}' d8e703d7e303

d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5

$ sudo cp file.txt /var/lib/docker/aufs/mnt/**d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5**/root/file.txt

13
Per me il percorso di montaggio dell'host non conteneva aufsma a devicemapper. Il modo più semplice per controllare il percorso di montaggio dei contenitori (mentre è in esecuzione) è eseguire il comando mount.
derenio,

3
Ho provato la soluzione sopra. Ha copiato i file nella directory specifica della finestra mobile. Tuttavia, quando uso bash per il contenitore docker, i file non vengono visualizzati lì. C'è qualcosa che mi manca?
AppleBud,

2
Il nuovo percorso è / var / lib / docker / devicemapper / mnt / <<id>> / rootfs /
mcuadros

4
Per me, su Docker 1.4.1 (attuale), è/var/lib/docker/aufs/diff/<id>/
user193130 il

3
che dire per gli utenti poveri di MacOS? La directory di mount è /var/libper me. find / -name dockernon è stato utile neanche.
Prayagupd,

141

Il modo più pulito è montare una directory host sul contenitore all'avvio del contenitore:

{host} docker run -v /path/to/hostdir:/mnt --name my_container my_image
{host} docker exec -it my_container bash
{container} cp /mnt/sourcefile /path/to/destfile

3
come si può eseguire il contenitore? ho pensato che puoi farlo solo con un'immagine.
Pavel Zaitsev,

Non riesco a farlo funzionare quando esiste un container aka è già stato eseguito prima. Il catrame qui sotto funziona bene.
Eino Mäkitalo,

1
L'unico modo in cui questo ha funzionato per me è stato quello di allegare il volume mentre eseguivo l'immagine (istanziando il contenitore). Finì con:docker run -d -p -v /host/path:/mnt --name container_name image_name
peter n

2
Questo non funziona per me. Atleast non può eseguire un contenitore. Può eseguire solo l'immagine
Shashank Hegde,

1
Sono sorpreso che docker cpsia un'operazione a senso unico!
ThorSummoner,

115

Quello che segue è un modo abbastanza brutto di farlo, ma funziona.

docker run -i ubuntu /bin/bash -c 'cat > file' < file

7
Funziona benissimo! Ma non dimenticate di confermare la modifica: docker commit `docker ps -l -q` ubuntu-with-file. Altrimenti la modifica andrà persa (usa il nome che preferisci invece di ubuntu-with-file)
Michael_Scharf,

@Erik: dove si trova il file quando il contenitore è in esecuzione?
coanor

49
In aggiunta, possiamo usare le nuove docker execfunzionalità per lavorare con il container in esecuzione:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl

17
@Mikl Penso che dovrebbe essere docker exec -i ...invece di -it, perché non c'è TTY quando si effettua il piping da un file.
z0r

4
Se sei ancora bloccato su una vecchia versione di Docker (come lo sono io) e vuoi copiare un'intera directory, puoi farlo: tar -c -v -f - /path/to/host/directory | docker exec -i <container-name> bash -c 'tar -x -v --strip-components 1 -f - -C /path/to/container/directory'
eahanson,

43

Se è necessario eseguire questa operazione su un container in esecuzione, è possibile utilizzare docker exec (aggiunto in 1.3).

Innanzitutto, trova il nome o l'ID del contenitore:

$ docker ps
CONTAINER ID        IMAGE                        COMMAND             CREATED             STATUS              PORTS                   NAMES
b9b7400ddd8f        ubuntu:latest                "/bin/bash"         2 seconds ago       Up 2 seconds                                elated_hodgkin

Nell'esempio sopra possiamo usare b9b7400ddd8fo elated_hodgkin.

Se si desidera copiare tutto /tmp/somefilesnell'host /var/wwwnel contenitore:

$ cd /tmp/somefiles
$ tar -cv * | docker exec -i elated_hodgkin tar x -C /var/www

Possiamo quindi eseguire /bin/bashnel contenitore e verificare che funzioni:

$ docker exec -it elated_hodgkin /bin/bash
root@b9b7400ddd8f:/# ls /var/www
file1  file2

Funziona alla grande su docker 1.16 su Centos 7.4 Ottima idea innovativa.
Dudi Boy,

41
  1. Crea un nuovo file docker e usa l'immagine esistente come base.

    FROM myName/myImage:latest
    
    ADD myFile.py bin/myFile.py
    
  2. Quindi compilare il contenitore:

    docker build .
    

2
Questo è ciò che ha funzionato per me. Nient'altro. Grazie!
Owen,

Creerà una nuova immagine, non direttamente un nuovo contenitore. Se riutilizzi questa immagine mentre myFile.py come modificato, utilizzerà la versione precedente del file, a meno che non ricostruisca l'immagine.
Guillaume Lebreton,

Trovo questo il modo più veloce solo se stai testando su un server remoto.
Dominik Krulak il

In base a ciò, la maggior parte delle persone dovrebbe usare COPIA anziché ADD. Ma per i file locali (come in questo esempio) sono equivalenti.
hoosierEE

39

La soluzione è riportata di seguito,

Dalla shell Docker,

root@123abc:/root#  <-- get the container ID

Dall'host

cp thefile.txt /var/lib/docker/devicemapper/mnt/123abc<bunch-o-hex>/rootfs/root

Il file deve essere copiato direttamente nella posizione in cui si trova il contenitore sul filesystem.


10
Bella risposta. Nelle versioni più recenti della finestra mobile il percorso è stato rinominato in / var / lib / docker / aufs / mnt /
Alex Volkov il

il percorso devicemapper non sembra funzionare su fedora con docker 1.6. L'ho messo come Q separato, stackoverflow.com/questions/29939419/… , ogni commento sarebbe apprezzato.
Yogesh_D

33

In genere ci sono tre tipi:

  1. Da un contenitore all'host

    docker cp container_id:./bar/foo.txt .
    

dev1

  1. Dall'host a un contenitore

    docker exec -i container_id sh -c 'cat > ./bar/foo.txt' < ./foo.txt
    

DEV2

  1. Da un contenitore a un contenitore mescola 1 e 2

    docker cp container_id1:./bar/foo.txt .
    
    docker exec -i container_id2 sh -c 'cat > ./bar/foo.txt' < ./foo.txt
    

dev3


6
docker cp funziona in entrambi i modi. Non c'è bisogno di exec, cat e reindirizzamento. docker cp host_file.txt container: / path /
tbm

32

Un'altra soluzione per copiare i file in un container in esecuzione sta usando tar:

tar -c foo.sh | docker exec -i theDockerContainer /bin/tar -C /tmp -x

Copia il file foo.shnel /tmpcontenitore.

Modifica: rimuovi redentant -f, grazie al commento di Maarten .


Questo è utile se devi inviare un'intera directory. Per un singolo file, la risposta di Erik è più semplice.
Kelvin,

1
@Kelvin: Ma tar conserva anche gli attributi e il nome del file. Tra le altre cose ciò significa che devi digitare il nome una sola volta (e lì otterrai il completamento della scheda dalla tua shell). Quindi direi che tar è in realtà più semplice, purché sia ​​installato nel contenitore.
Maarten,

1
Il -f -è un po 'ridondante, però, il comportamento predefinito è quello di scrivere a stdout comunque.
Maarten,

ciò significa che esiste una dipendenza host da tar
cellige il

Hai ragione: è necessario che tar sia installato sull'host e all'interno del contenitore. Oggi l'utilizzo della docker cp è la soluzione migliore.
joemat,

24

Per copiare un file dall'host al contenitore in esecuzione

docker exec -i $CONTAINER /bin/bash -c "cat > $CONTAINER_PATH" < $HOST_PATH

Basato sulla risposta di Erik e sui commenti di Mikl e z0r.


Le soluzioni accettate a volte disturbano il rientro dei file durante il trasferimento in contenitori in esecuzione. Funziona perfettamente in questi casi
Dreams


15

Questa è una risposta diretta alla domanda "Copia di file dall'host al contenitore Docker" sollevata in questa domanda nel titolo.

Prova docker cp. È il modo più semplice per farlo e funziona anche sul mio Mac. Uso:

docker cp /root/some-file.txt some-docker-container:/root

Questo copierà il file some-file.txtnella directory /rootsul tuo computer host nel contenitore Docker nominato some-docker-containernella directory /root. È molto vicino alla sintassi della copia sicura. E come mostrato nel post precedente, puoi usarlo viceversa. Vale a dire, si copiano anche i file dal contenitore all'host.

E prima di effettuare il downlink di questo post, inserisci docker cp --help. Leggere la documentazione può essere molto utile, a volte ...

Se non ti piace in questo modo e desideri volumi di dati nel contenitore già creato ed in esecuzione, la ricreazione è la tua unica opzione oggi. Vedi anche Come posso aggiungere un volume a un contenitore Docker esistente? .


15

Ho provato la maggior parte delle soluzioni (aggiornate) qui, ma nella docker 17.09 (nel 2018) non esiste più la cartella / var / lib / docker / aufs.

Questo semplice docker cprisolto questo compito.

docker cp c:\path\to\local\file container_name:/path/to/target/dir/

Come ottenere container_name?

 docker ps 

C'è una NAMESsezione Non usare a IMAGE.


12

Per copiare file / cartelle tra un contenitore e il filesystem locale, digitare il comando:

docker cp {SOURCE_FILE} {DESTINATION_CONTAINER_ID}:/{DESTINATION_PATH}

Per esempio,

docker cp /home/foo container-id:/home/dir

Per ottenere l'id contianer, digitare il comando dato:

docker ps

Il contenuto sopra è tratto da docker.com .


8

Supponendo che il contenitore sia già in esecuzione, digitare il comando dato:

# cat /path/to/host/file/ | docker exec -i -t <container_id> bash -c "/bin/cat > /path/to/container/file"

Per condividere i file utilizzando la directory condivisa, eseguire il contenitore digitando il comando indicato:

# docker run -v /path/to/host/dir:/path/to/container/dir ...

Nota: potrebbero sorgere problemi con le autorizzazioni poiché gli utenti del contenitore non sono gli stessi degli utenti dell'host.


1
Inoltre:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl,

2
Nota che catnon verrà terminato una volta uscito. Se è importante per te (se stai copiando script bash, bash rifiuterà di eseguirli), dovresti eseguire lsof | grep yourfilenamee terminare il catprocesso che contiene quel file.
johndodo,

Grazie! Ottimo consiglio Puoi dirmi come interrompere questo processo con un comando? Qualcosa del genere kill $(lsof | grep /path/to/file | sed ...). Ti sarò grato per il tuo aiuto
Mikl,

kill $(docker top CONTAINERNAME | sed -n '/cat$/p' | sed 's/^root[^0-9]\+\([0-9]\+\).*$/\1/')
Mikl

8

Questo è il comando per copiare dati da Docker a Host:

docker cp container_id:file path/filename /hostpath

docker cp a13fb9c9e674:/tmp/dgController.log /tmp/

Di seguito è riportato il comando per copiare i dati dall'host alla finestra mobile:

docker cp a.txt ccfbeb35116b:/home/

7

In un ambiente docker, tutti i contenitori si trovano nella directory:

/var/lib/docker/aufs/required-docker-id/

Per copiare la directory / file di origine in qualsiasi parte del contenitore, digitare il comando dato:

sudo cp -r mydir/ /var/lib/docker/aufs/mnt/required-docker-id/mnt/


5

tare docker cpsono una buona combinazione per copiare tutto in una directory.

Creare un contenitore del volume di dati

docker create --name dvc --volume /path/on/container cirros

Per preservare la gerarchia di directory

tar -c -C /path/on/local/machine . | docker cp - dvc:/path/on/container

Controlla il tuo lavoro

docker run --rm --volumes-from dvc cirros ls -al /path/on/container

5

Se l'host è CentOS o Fedora, c'è un proxy NON in /var/lib/docker/aufs, ma è sotto /proc:

cp -r /home/user/mydata/* /proc/$(docker inspect --format "{{.State.Pid}}" <containerid>)/root

Questo cmd copia tutti i contenuti della datadirectory nel /contenitore con ID "containerid".


Questo non è univoco per Redhat: funziona anche su Debian. (forse tutto Gnu / Linux con /proc). Estendi anche il percorso per mettere il file altrove, non solo root.
ctrl-alt-delor,

5

Nel caso in cui a qualcuno come me non sia chiaro cosa significhi mycontainerin @ h3nrik la risposta, in realtà è l'ID contenitore. Per copiare un file WarpSquare.mp4in /app/example_scenes/1440p60da un contenitore finestra mobile uscito alla cartella corrente ho usato questo.

docker cp `docker ps -q -l`:/app/example_scenes/1440p60/WarpSquare.mp4 .

dove docker ps -q -lrichiama l'ID contenitore dell'ultima istanza uscita. Nel caso in cui non sia un contenitore uscito, puoi ottenerlo da docker container lsodocker ps


1
È possibile elencare gli ID dei contenitori usciti con docker ps -ao docker container ls -a.
0x7d7b

4

Molti che trovano questa domanda potrebbero effettivamente avere il problema di copiare i file in un'immagine Docker mentre viene creata (l'ho fatto).

In tal caso, è possibile utilizzare il COPYcomando in Dockerfileche si utilizza per creare l'immagine.

Vedere la documentazione .


4

Puoi semplicemente tracciare l'indirizzo IP del tuo computer locale usando

ifconfig

Quindi entra nel contenitore Docker e digita

scp user_name@ip_address:/path_to_the_file destination

In ogni caso se non hai installato un client e un server SSH, installalo semplicemente usando:

sudo apt-get install openssh-server

Grazie mille, ha funzionato bene per me. Inoltre, l'ho trovato più efficiente di altri modi
user1314742

Questa è una soluzione orribile in termini di sicurezza.

4

Questo è un onliner per la copia di un singolo file durante l'esecuzione di un contenitore Tomcat.

docker run -v /PATH_TO_WAR/sample.war:/usr/local/tomcat/webapps/myapp.war -it -p 8080:8080 tomcat

Questo copierà il file di guerra nella directory di webapps e farà funzionare la tua app in pochissimo tempo.


1
-v monterà (cioè creerà un collegamento), non copia
Vitaliy Ulantikov il

la differenza nel risultato è che il montaggio nasconde il contenuto del contenitore precedente, ad esempio se si monta una cartella host su una cartella contenitore non è più possibile visualizzare il contenuto della cartella contenitore precedente
mrq

4

Sintassi contenitore:

 docker run -v /HOST/folder:/Container/floder 

Nel file docker

COPY hom* /myFolder/        # adds all files starting with "hom"
COPY hom?.txt /myFolder/    # ? is replaced with any single character, e.g., "home.txt"

3

Il modo migliore per copiare i file nel contenitore che ho trovato è montare una directory sull'host usando l' -vopzione del comando docker run.


3

Ci sono buone risposte, ma troppo specifiche. Scopro che docker psè un buon modo per ottenere l'ID contenitore che ti interessa. Allora fallo

mount | grep <id>

per vedere dove è montato il volume. Quello è

/var/lib/docker/devicemapper/mnt/<id>/rootfs/

per me, ma potrebbe essere un percorso diverso a seconda del sistema operativo e della configurazione. Ora copia semplicemente i file su quel percorso.

L'uso -vnon è sempre pratico.


3

Ho appena iniziato a utilizzare la finestra mobile per compilare VLC, ecco cosa puoi fare per copiare i file avanti e indietro dai contenitori:

su -
cd /var/lib/docker
ls -palR > /home/user/dockerfilelist.txt

Cerca un file familiare in quel txt e avrai la cartella, cd come root e voilà! copia tutto quello che vuoi.

Potrebbe esserci un percorso con "unito" in esso, immagino che tu voglia quello con "diff" in esso.

Inoltre, se esci dal contenitore e desideri tornare da dove avevi interrotto:

docker ps -a
docker start -i containerid

Immagino che sia utile quando non hai nominato nulla con un comando come

docker run -it registry.videolan.org:5000/vlc-debian-win64 /bin/bash

Sicuro il metodo hacker ma che importa!


3
docker cp SRC_PATH CONTAINER_ID:DEST_PATH

Ad esempio, voglio copiare il mio file xxxx / download / jenkins su tomcat

Comincio a ottenere l'id del contenitore Tomcat

docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
63686740b488        tomcat              "catalina.sh run"   12 seconds ago      Up 11 seconds       0.0.0.0:8080->8080/tcp   peaceful_babbage

docker cp xxxx/download/jenkins.war  63686740b488:usr/local/tomcat/webapps/

2

Il mio metodo preferito:

CONTENITORI:

CONTAINER_ID=$(docker ps | grep <string> | awk '{ print $1 }' | xargs docker inspect -f '{{.Id}}')

file.txt

mv -f file.txt /var/lib/docker/devicemapper/mnt/$CONTAINER_ID/rootfs/root/file.txt

o

mv -f file.txt /var/lib/docker/aufs/mnt/$CONTAINER_ID/rootfs/root/file.txt

il percorso devicemapper non sembra funzionare su fedora con docker 1.6. L'ho messo come Q separato, stackoverflow.com/questions/29939419/… , ogni commento sarebbe apprezzato.
Yogesh_D

2

Secondo me non devi copiare file all'interno dell'immagine ma puoi usare GIT o SVN per i tuoi file e quindi impostare un volume sincronizzato con una cartella locale. Utilizzare uno script durante l'esecuzione del contenitore che può verificare se i dati esistono già nella cartella locale se non copiarli dal repository GIT. Ciò rende la tua immagine molto leggera.


Questo sembra un rischio per la sicurezza e l'accesso all'incubo in attesa di accadere. Come si fornisce l'accesso al repository git dall'interno dell'immagine? Anche supponendo che sia un repository pubblico, supponiamo che l'host su cui è in esecuzione il container abbia accesso a quel repository.
martedì

Sono d'accordo con te se git viene usato all'interno del container docker. Ma nel nostro caso, lo script è in esecuzione dalla macchina host
h.aittamaa
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.