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.