Kopiowanie plików z hosta do kontenera Docker


1574

Próbuję zbudować rozwiązanie do tworzenia kopii zapasowych i przywracania dla kontenerów Docker, z którymi współpracujemy.

Mam podstawowy obraz Dockera, który utworzyłem ubuntu:basei nie chcę go za każdym razem przebudowywać za pomocą pliku Docker, aby dodać do niego pliki.

Chcę utworzyć skrypt uruchamiany z komputera hosta i tworzy nowy kontener za pomocą ubuntu:baseobrazu Docker, a następnie kopiuje pliki do tego kontenera.

Jak mogę skopiować pliki z hosta do kontenera?


11
Jeśli nie chcesz odbudowywać, dlaczego nie „ zatwierdzić dokera ”? To zapisuje twój obraz.
Berend de Boer

26
Tylko uwaga na temat pojęcia, do którego nikt się nie odniósł: ogólnie traktuj pojemniki jako „efemeryczne”. Istnieją przypadki użycia do kopiowania plików do / z działającego kontenera (testowanie, prototypowanie). Ale jeśli znajdziesz się w sytuacji, w której nie możesz odbudować tego, czego potrzebujesz za pomocą Dockerfiles i / lub komponować, możesz być w złym miejscu. Zasadniczo nie chcesz tworzyć kopii zapasowych kontenerów tak, jakby były one obiektami systemu operacyjnego lub nawet maszyn wirtualnych. Ogólnie rzecz biorąc :-)
Scott Prive

Odpowiedzi:


2670

cpKomenda może być używany do kopiowania plików.

Jeden konkretny plik można skopiować do kontenera, na przykład:

docker cp foo.txt mycontainer:/foo.txt

Jeden konkretny plik można skopiować z kontenera, np .:

docker cp mycontainer:/foo.txt foo.txt

Dla podkreślenia, mycontainerto pojemnik ID, nie obrazu ID.

Wiele plików zawartych w folderze srcmożna skopiować do targetfolderu za pomocą:

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

Odniesienie: Dokumentacja interfejsu Docker CLI dlacp

W wersjach Docker wcześniejszych niż 1.8 możliwe było tylko kopiowanie plików z kontenera na host. Nie od hosta do kontenera.


2
zauważ również, że może to być na vm hosta lub głównym systemie operacyjnym i działa albo z hosta do kontenera, albo z vm na hosta (lub main os)
Adam Tuliper - MSFT

7
W Dockerfile możesz użyć słowa kluczowego ADD, aby dodać pliki podczas kompilacji.
0x7d7b

4
@ h3nrik COPYpreferowane,ADD jeśli dotyczy.
Franklin Yu,

10
służy docker cpdo kopiowania z kontenera do hosta działa dobrze, ale kiedy używasz go do kopiowania plików z hosta do kontenera, bez efektu ... ktoś wie dlaczego? wersja dokera: wersja Docker 1.10.3, kompilacja cb079f6-nieobsługiwana
Ace.Yin

2
Czy mogę skopiować wiele plików przy użyciu dokera cp z hosta do kontenera?
Jogesh,

182
  1. Uzyskaj nazwę kontenera lub krótki identyfikator kontenera:

    $ docker ps
    
  2. Uzyskaj pełny identyfikator kontenera:

    $ docker inspect -f   '{{.Id}}'  SHORT_CONTAINER_ID-or-CONTAINER_NAME
    
  3. Skopiować plik:

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

PRZYKŁAD:

$ 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

lub

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

d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5

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

13
Dla mnie ścieżka montowania hosta nie zawierała, aufstylko devicemapper. Najłatwiejszym sposobem sprawdzenia ścieżki montażu kontenerów (gdy jest ona uruchomiona) jest uruchomienie polecenia mount.
derenio

3
Wypróbowałem powyższe rozwiązanie. Skopiował pliki do określonego katalogu dokera. Jednak gdy używam bash jako kontenera dokującego, pliki się tam nie wyświetlają. Czy czegoś brakuje?
AppleBud,

2
Nowa ścieżka to / var / lib / docker / devicemapper / mnt / <<id>> / rootfs /
mcuadros

4
Dla mnie, w Docker 1.4.1 (najnowszy najnowszy), to/var/lib/docker/aufs/diff/<id>/
193130

3
co z biednymi użytkownikami MacOS? Katalog montowania jest /var/libdla mnie. find / -name dockerteż nie było pomocne.
prayagupd

141

Najczystszym sposobem jest zamontowanie katalogu hosta na kontenerze podczas uruchamiania kontenera:

{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
jak uruchomić kontener? myślałem, że możesz to zrobić tylko z obrazem.
Pavel Zaitsev

Nie mogę go uruchomić, gdy istnieje kontener, czyli wcześniej działał jako aka. Smoła poniżej działa dobrze.
Eino Mäkitalo

1
Jedynym sposobem, w jaki mi to działało, było dołączenie woluminu wraz z uruchomieniem obrazu (utworzenie instancji kontenera). Skończyło się na:docker run -d -p -v /host/path:/mnt --name container_name image_name
Peter n

2
To mi nie działa. Przynajmniej nie można uruchomić kontenera. Można uruchomić tylko obraz
Shashank Hegde

1
Dziwi mnie, że docker cpto operacja jednostronna!
ThorSummoner

115

Poniższy sposób jest dość brzydki, ale działa.

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

7
To działa świetnie! Ale nie zapomnij, aby zatwierdzić zmiany: docker commit `docker ps -l -q` ubuntu-with-file. W przeciwnym razie zmiana zostanie utracona (użyj dowolnego imienia zamiast ubuntu-with-file)
Michael_Scharf,

@Erik: Gdzie znajduje się plik podczas działania kontenera?
coanor,

49
Dodatkowo możemy użyć nowej docker execfunkcji do pracy z uruchomionym kontenerem:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl

17
@Mikl Myślę, że powinno być docker exec -i ...zamiast -it, ponieważ nie ma TTY podczas przesyłania z pliku.
z0r

4
Jeśli nadal tkwisz w starej wersji Dockera (tak jak ja) i chcesz skopiować cały katalog, możesz to zrobić: 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

Jeśli musisz to zrobić na działającym kontenerze, możesz użyć exec Dockera (dodany w 1.3).

Najpierw znajdź nazwę lub identyfikator pojemnika:

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

W powyższym przykładzie możemy użyć b9b7400ddd8falbo elated_hodgkin.

Jeśli chcesz skopiować wszystko /tmp/somefilesna hoście do /var/wwwkontenera:

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

Następnie możemy wykonać /bin/bashw kontenerze i sprawdzić, czy zadziałało:

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

Działa świetnie w oknie dokowanym 1.16 w Centos 7.4 Świetny innowacyjny pomysł.
Dudi Boy

41
  1. Utwórz nowy plik dokera i użyj istniejącego obrazu jako podstawy.

    FROM myName/myImage:latest
    
    ADD myFile.py bin/myFile.py
    
  2. Następnie zbuduj kontener:

    docker build .
    

2
To działało dla mnie. Nic więcej. Dziękuję Ci!
Owen

Stworzy nowy obraz, a nie bezpośrednio nowy kontener. Jeśli użyjesz tego obrazu ponownie, gdy plik myFile.py został zmieniony, użyje starszej wersji pliku, chyba że odbudujesz obraz.
Guillaume Lebreton,

Uważam to za najszybszy sposób tylko wtedy, gdy testujesz na zdalnym serwerze.
Dominik Krulak,

Zgodnie z tym większość ludzi powinna używać KOPIOWANIA zamiast DODAJ. Ale dla plików lokalnych (jak w tym przykładzie) są one równoważne.
hoosierEE

39

Rozwiązanie podano poniżej,

Z powłoki Dockera

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

Od gospodarza

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

Plik należy skopiować bezpośrednio do lokalizacji, w której kontener znajduje się w systemie plików.


10
Świetna odpowiedź. W nowszych wersjach dokera nazwa ścieżki została zmieniona na / var / lib / docker / aufs / mnt /
Alex Volkov

ścieżka devicemapper nie wydaje się działać na fedorze z dokerem 1.6. Postawiłem to jako osobne Q, stackoverflow.com/questions/29939419/… , wszelkie komentarze będą mile widziane.
Yogesh_D

33

Zazwyczaj są trzy typy:

  1. Od kontenera do hosta

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

dev1

  1. Od hosta do kontenera

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

dev2

  1. Z pojemnika do pojemnika miesza 1 i 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 działa w obie strony. Nie trzeba wykonywać poleceń, cat i przekierowywać. docker cp plik_hosta.txt kontener: / path /
tbm

32

Innym rozwiązaniem do kopiowania plików do działającego kontenera jest użycie tar:

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

Kopiuje plik foo.shdo /tmpkontenera.

Edycja: Usuń reduntant -f, dzięki komentarzowi Maarten .


Jest to dobre, jeśli musisz wysłać cały katalog. W przypadku pojedynczego pliku odpowiedź Erika jest prostsza.
Kelvin,

1
@ Kelvin: Ale tar zachowuje również atrybuty i nazwę pliku. Oznacza to między innymi, że musisz wpisać nazwę tylko raz (i tam otrzymasz uzupełnienie tabulatora ze swojej powłoki). Powiedziałbym więc, że tar jest w rzeczywistości prostszy, o ile jest zainstalowany w kontenerze.
Maarten,

1
Jest -f -to jednak trochę zbędne, domyślnym zachowaniem jest jednak pisanie na standardowe wyjście.
Maarten,

oznacza to, że istnieje zależność hosta od tar
cellige

Masz rację - musisz zainstalować tar na hoście i w kontenerze. Obecnie używanie dokera cp jest lepszym rozwiązaniem.
joemat

24

Aby skopiować plik z hosta do uruchomionego kontenera

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

Na podstawie odpowiedzi Erika i komentarzy Mikla i z0r.


Przyjęte rozwiązania czasami zakłócają wcięcia plików podczas przesyłania do uruchomionych kontenerów. Działa to idealnie w takich przypadkach
Dreams


15

To jest bezpośrednia odpowiedź na pytanie „Kopiowanie plików z hosta do kontenera Docker” postawione w tym pytaniu w tytule.

Spróbować docker cp. Jest to najprostszy sposób, aby to zrobić i działa nawet na moim komputerze Mac. Stosowanie:

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

Spowoduje to skopiowanie pliku some-file.txtz katalogu /rootna komputerze hosta do kontenera Docker o nazwie podanej w some-docker-containerkatalogu /root. Jest to bardzo zbliżone do bezpiecznej składni kopii. I jak pokazano w poprzednim poście, możesz użyć go na odwrót. To znaczy, kopiujesz również pliki z kontenera na host.

I zanim prześlesz ten post w dół, wpisz docker cp --help. Czytanie dokumentacji może być bardzo pomocne, czasami ...

Jeśli nie podoba ci się w ten sposób i chcesz mieć woluminy danych w już utworzonym i działającym kontenerze, odtwarzanie jest dziś twoją jedyną opcją. Zobacz także Jak mogę dodać wolumin do istniejącego kontenera Docker? .


15

Wypróbowałem tutaj większość (pozytywnych) rozwiązań, ale w oknie dokowanym 17.09 (w 2018 r.) Nie ma już folderu / var / lib / docker / aufs.

To proste docker cprozwiązało to zadanie.

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

Jak zdobyć nazwę kontenera?

 docker ps 

Jest NAMESsekcja. Nie używaj IMAGE.


12

Aby skopiować pliki / foldery między kontenerem a lokalnym systemem plików, wpisz polecenie:

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

Na przykład,

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

Aby uzyskać identyfikator contianer, wpisz podane polecenie:

docker ps

Powyższa treść pochodzi z witryny docker.com .


8

Zakładając, że kontener już działa, wpisz podane polecenie:

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

Aby udostępnić pliki za pomocą udostępnionego katalogu, uruchom kontener, wpisując podane polecenie:

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

Uwaga: mogą wystąpić problemy z uprawnieniami, ponieważ użytkownicy kontenera nie są tacy sami jak użytkownicy hosta.


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

2
Pamiętaj, że catnie zostanie zakończone po wyjściu. Jeśli ma to dla ciebie znaczenie (jeśli kopiujesz skrypty bash, bash odmówi ich uruchomienia), powinieneś uruchomić lsof | grep yourfilenamei zabić catproces, który przechowuje wspomniany plik.
johndodo

Dzięki! Świetna wskazówka. Czy możesz mi powiedzieć, jak zabić ten proces za pomocą jednego polecenia? Coś jak kill $(lsof | grep /path/to/file | sed ...). Będę wdzięczny za twoją pomoc
Mikl

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

8

Oto polecenie kopiowania danych z Dockera na Host:

docker cp container_id:file path/filename /hostpath

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

Poniżej znajduje się polecenie kopiowania danych z hosta do dokera:

docker cp a.txt ccfbeb35116b:/home/

7

W środowisku dokera wszystkie kontenery znajdują się w katalogu:

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

Aby skopiować katalog / plik źródłowy do dowolnej części kontenera, wpisz podane polecenie:

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


5

tari docker cpsą dobrym zestawem do kopiowania wszystkiego w katalogu.

Utwórz kontener woluminu danych

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

Aby zachować hierarchię katalogów

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

Sprawdź swoją pracę

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

5

Jeśli hostem jest CentOS lub Fedora, serwer proxy NIE jest w /var/lib/docker/aufs, ale znajduje się poniżej /proc:

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

To polecenie cmd skopiuje całą zawartość datakatalogu do /kontenera o identyfikatorze „containerid”.


Nie jest to unikalne dla Redhat: działa również na Debianie. (może wszystkie Gnu / Linux z /proc). Rozszerz także ścieżkę, aby umieścić plik w innym miejscu, nie tylko root.
ctrl-alt-delor

5

W przypadku, gdy dla kogoś takiego jak ja nie jest jasne, co mycontaineroznacza odpowiedź @ h3nrik, w rzeczywistości jest to identyfikator kontenera. Aby skopiować plik WarpSquare.mp4w /app/example_scenes/1440p60od wyszły pojemnika Döcker do bieżącego folderu użyłem tego.

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

gdzie docker ps -q -lpobiera identyfikator kontenera ostatniej opuszczonej instancji. W przypadku, gdy nie jest to opuszczony pojemnik, możesz go zdobyć przez docker container lslubdocker ps


1
Możesz wyświetlić listę identyfikatorów wychodzących kontenerów za pomocą docker ps -alub docker container ls -a.
0x7d7b,

4

Wiele osób, które znajdą to pytanie, może faktycznie mieć problem z kopiowaniem plików do obrazu Docker podczas jego tworzenia (ja to zrobiłem).

W takim przypadku możesz użyć COPYpolecenia Dockerfileużytego do utworzenia obrazu.

Zobacz dokumentację .


4

Możesz po prostu prześledzić adres IP swojego komputera lokalnego za pomocą

ifconfig

Następnie po prostu wejdź do swojego kontenera Docker i wpisz

scp user_name@ip_address:/path_to_the_file destination

W każdym razie, jeśli nie masz zainstalowanego klienta SSH i serwera, po prostu zainstaluj go za pomocą:

sudo apt-get install openssh-server

Dzięki bardzo, działało to dla mnie dobrze. Ponadto uważam, że jest bardziej wydajny niż inne sposoby
user1314742,

To okropne rozwiązanie pod względem bezpieczeństwa.

4

Jest to narzędzie do kopiowania pojedynczego pliku podczas uruchamiania kontenera tomcat.

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

Spowoduje to skopiowanie pliku wojny do katalogu webapps i uruchomienie aplikacji w krótkim czasie.


1
-v zamontuje (tzn. utworzy link), a nie kopiuje
Vitaliy Ulantikov

różnica w wyniku polega na tym, że podczas montowania ukrywa się poprzednia zawartość kontenera, np. jeśli zamontujesz folder hosta na folderze kontenera, nie będziesz już widzieć zawartości poprzedniego folderu kontenera
mrq

4

Składnia w górę kontenera:

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

W pliku dokera

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

3

Najlepszym sposobem na skopiowanie plików do kontenera, który znalazłem, jest zamontowanie katalogu na hoście przy użyciu -vopcji polecenia docker run.


3

Istnieją dobre odpowiedzi, ale zbyt szczegółowe. Okazało się, że docker psto dobry sposób na uzyskanie identyfikatora kontenera, który Cię interesuje

mount | grep <id>

aby zobaczyć, gdzie zamontowano wolumin. To jest

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

dla mnie, ale może to być inna ścieżka w zależności od systemu operacyjnego i konfiguracji. Teraz wystarczy skopiować pliki do tej ścieżki.

Korzystanie -vnie zawsze jest praktyczne.


3

Właśnie zacząłem używać dokera do kompilacji VLC, oto co możesz zrobić, aby skopiować pliki tam iz powrotem z kontenerów:

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

Wyszukaj znajomy plik w tym txt, a będziesz mieć folder, cd do niego jako root i voila! skopiuj wszystko, co chcesz.

Może być ścieżka z „scalonymi”, myślę, że chcesz tę z „diff”.

Również jeśli wyjdziesz z kontenera i chcesz wrócić tam, gdzie go przerwałeś:

docker ps -a
docker start -i containerid

Wydaje mi się, że jest to przydatne, gdy nic nie nazwałeś poleceniem typu

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

Pewnie metoda hakera, ale co z tego!


3
docker cp SRC_PATH CONTAINER_ID:DEST_PATH

Na przykład chcę skopiować mój plik xxxx / download / jenkins do tomcat

Zaczynam dostawać identyfikator kontenera 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

Moja ulubiona metoda:

POJEMNIKI:

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

plik.txt

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

lub

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

ścieżka devicemapper nie wydaje się działać na fedorze z dokerem 1.6. Postawiłem to jako osobne Q, stackoverflow.com/questions/29939419/… , wszelkie komentarze będą mile widziane.
Yogesh_D

2

Moim zdaniem nie musisz kopiować plików wewnątrz obrazu, ale możesz użyć GIT lub SVN dla swoich plików, a następnie ustawić wolumin zsynchronizowany z folderem lokalnym. Użyj skryptu podczas uruchamiania kontenera, który może sprawdzić, czy dane już istnieją w folderze lokalnym, jeśli nie skopiuj go z repozytorium GIT. Dzięki temu Twój obraz jest bardzo lekki.


To wydaje się być zagrożeniem bezpieczeństwa i koszmarem dostępu, który czeka. Jak zapewniasz dostęp do repozytorium git z poziomu twojego obrazu? Nawet zakładając, że jest to repozytorium publiczne, zakładasz, że host, na którym działa kontener, ma dostęp do tego repozytorium.
tbm

Zgadzam się z tobą, jeśli git jest używany w kontenerze dokera. Ale w naszym przypadku skrypt jest uruchamiany z komputera hosta
h.aittamaa
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.