Menyalin file dari host ke wadah Docker


1581

Saya mencoba membangun solusi cadangan dan memulihkan untuk wadah Docker yang bekerja dengan kami.

Saya memiliki gambar dasar Docker yang telah saya buat,, ubuntu:basedan tidak ingin harus membangunnya kembali setiap kali dengan file Docker untuk menambahkan file ke dalamnya.

Saya ingin membuat skrip yang dijalankan dari mesin host dan membuat wadah baru menggunakan ubuntu:basegambar Docker dan kemudian menyalin file ke wadah itu.

Bagaimana saya bisa menyalin file dari host ke wadah?


12
Jika Anda tidak ingin membangun kembali, mengapa tidak " buruh pelabuhan berkomitmen "? Itu menghemat gambar Anda.
Berend de Boer

28
Hanya komentar tentang gagasan yang belum pernah ditangani oleh siapa pun: secara umum, perlakukan wadah sebagai "sesaat". ADA kasus yang digunakan untuk menyalin file ke / dari wadah yang sedang berjalan (pengujian, pembuatan prototipe). Tetapi jika Anda menemukan diri Anda dalam posisi di mana Anda tidak dapat membangun kembali apa yang Anda butuhkan menggunakan Dockerfiles dan / atau menulis, maka Anda mungkin berada di tempat yang buruk. Anda biasanya tidak ingin membuat cadangan kontainer seolah-olah mereka OS atau bahkan objek VM. Secara umum :-)
Scott Prive

Jawaban:


2674

The cpperintah dapat digunakan untuk menyalin file.

Satu file tertentu dapat disalin ke wadah seperti:

docker cp foo.txt mycontainer:/foo.txt

Satu file spesifik dapat disalin dari wadah seperti:

docker cp mycontainer:/foo.txt foo.txt

Untuk penekanan, mycontaineradalah wadah ID, bukan sebuah gambar ID.

Beberapa file yang terkandung oleh folder srcdapat disalin ke dalam targetfolder menggunakan:

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

Referensi: Dokumentasi CLI Docker untukcp

Dalam versi Docker sebelum 1.8, hanya mungkin untuk menyalin file dari sebuah wadah ke host. Bukan dari host ke wadah.


2
juga perhatikan ini bisa di host vm atau OS utama dan berfungsi baik host ke container atau vm to host (atau os utama)
Adam Tuliper - MSFT

7
Dalam Dockerfile Anda dapat menggunakan kata kunci ADD untuk menambahkan file selama waktu pembuatan.
0x7d7b

4
@ h3nrik COPYlebih disukai daripadaADD saat berlaku.
Franklin Yu

10
gunakan docker cpuntuk menyalin dari wadah ke host berfungsi dengan baik, tetapi ketika menggunakannya untuk menyalin file dari host ke wadah, tidak ada efek ... ada yang tahu mengapa? versi docker: Docker versi 1.10.3, build cb079f6-unsupported
Ace.Yin

2
Bisakah saya menyalin beberapa file menggunakan docker cp dari host ke container?
Yogesh

182
  1. Dapatkan nama wadah atau id wadah pendek:

    $ docker ps
    
  2. Dapatkan id kontainer lengkap:

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

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

CONTOH:

$ 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

atau

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

d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5

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

13
Bagi saya jalur pemasangan host tidak mengandung aufstetapi a devicemapper. Cara termudah untuk memeriksa jalur pemasangan kontainer (saat sedang berjalan) adalah dengan menjalankan perintah mount.
derenio

3
Saya mencoba solusi di atas. Itu menyalin file ke direktori spesifik buruh pelabuhan. Namun, ketika saya menggunakan bash untuk wadah buruh pelabuhan, file tidak muncul di sana. Apakah ada sesuatu yang saya lewatkan?
AppleBud

2
Path baru adalah / var / lib / docker / devicemapper / mnt / <<id>> / rootfs /
mcuadros

4
Bagi saya, di Docker 1.4.1 (terbaru saat ini), itu/var/lib/docker/aufs/diff/<id>/
user193130

3
bagaimana dengan untuk pengguna MacOS yang buruk? Direktori mount /var/libuntuk saya. find / -name dockerjuga tidak membantu.
prayagupd

141

Cara terbersih adalah memasang direktori host pada wadah ketika memulai wadah:

{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
bagaimana Anda bisa menjalankan kontainer? saya pikir Anda hanya dapat melakukannya dengan gambar.
Pavel Zaitsev

Saya tidak bisa membuatnya bekerja ketika wadah sudah ada alias telah berjalan sebelumnya. Tar di bawah ini berfungsi dengan baik.
Eino Mäkitalo

1
Satu-satunya cara ini berhasil bagi saya adalah melampirkan volume di samping menjalankan gambar (instantiating the container). Berakhir dengan:docker run -d -p -v /host/path:/mnt --name container_name image_name
peter n

2
Ini tidak bekerja untuk saya. Atleast tidak dapat menjalankan wadah. Hanya dapat menjalankan gambar
Shashank Hegde

1
Saya kagum bahwa docker cpini adalah operasi satu arah!
ThorSummoner

115

Berikut ini adalah cara yang cukup buruk untuk melakukannya tetapi berhasil.

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

7
Ini sangat bagus! Tapi jangan lupa untuk melakukan perubahan: docker commit `docker ps -l -q` ubuntu-with-file. Jika tidak, perubahan akan hilang (gunakan nama apa pun yang Anda inginkan ubuntu-with-file)
Michael_Scharf

@Erik: Di mana file tersebut berada saat wadah berjalan?
coanor

49
Selain itu, kita dapat menggunakan docker execfitur baru untuk bekerja dengan menjalankan wadah:docker exec -it <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
Mikl

17
@ Mik saya pikir itu seharusnya docker exec -i ...bukan -it, karena tidak ada TTY ketika menyalurkan dari file.
z0r

4
Jika Anda masih terjebak pada versi lama Docker (seperti saya) dan ingin menyalin seluruh direktori, Anda dapat melakukan ini: 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

Jika Anda perlu melakukan ini pada wadah yang sedang berjalan, Anda dapat menggunakan docker exec (ditambahkan pada 1.3).

Pertama, temukan nama atau ID wadah:

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

Dalam contoh di atas kita dapat menggunakan b9b7400ddd8fatau elated_hodgkin.

Jika Anda ingin menyalin semua yang ada di /tmp/somefileshost ke /var/wwwdalam wadah:

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

Kami kemudian dapat mengeksekusi /bin/bashdalam wadah dan memverifikasi itu berfungsi:

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

Bekerja sangat baik di atas buruh pelabuhan 1,16 pada Centos 7.4 Ide inovatif yang hebat.
Dudi Boy

41
  1. Buat dockerfile baru dan gunakan gambar yang ada sebagai basis Anda.

    FROM myName/myImage:latest
    
    ADD myFile.py bin/myFile.py
    
  2. Kemudian bangun wadah:

    docker build .
    

2
Inilah yang bekerja untuk saya. Tidak ada lagi. Terima kasih!
Owen

Ini akan membuat gambar baru, bukan langsung wadah baru. Jika Anda menggunakan kembali gambar ini ketika myFile.py sebagai diubah, itu akan menggunakan versi file yang lebih lama, kecuali jika Anda membangun kembali gambar.
Guillaume Lebreton

Saya menemukan ini cara tercepat hanya jika Anda menguji pada server jauh.
Dominik Krulak

Menurut ini kebanyakan orang harus menggunakan COPY daripada ADD. Tetapi untuk file lokal (seperti dalam contoh ini) mereka setara.
hoosierEE

39

Solusinya diberikan di bawah ini,

Dari shell Docker,

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

Dari tuan rumah

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

File harus disalin secara langsung ke lokasi di mana wadah berada di sistem file.


10
Jawaban yang bagus Dalam rilis docker yang lebih baru path telah diubah namanya menjadi / var / lib / docker / aufs / mnt /
Alex Volkov

jalur devicemapper tampaknya tidak berfungsi pada fedora dengan docker 1.6. Telah meletakkannya sebagai Q terpisah, stackoverflow.com/questions/29939419/... , komentar apa pun akan dihargai.
Yogesh_D

33

Biasanya ada tiga jenis:

  1. Dari wadah ke tuan rumah

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

dev1

  1. Dari host ke wadah

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

dev2

  1. Dari wadah ke wadah campuran 1 dan 2

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

dev3


6
buruh pelabuhan cp bekerja dua arah. Tidak perlu exec, cat, dan redirect. docker cp host_file.txt wadah: / path /
tbm

32

Solusi lain untuk menyalin file ke wadah berjalan menggunakan tar:

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

Menyalin file foo.shke /tmpdalam wadah.

Sunting: Hapus reduntant -f, terima kasih atas komentar Maarten .


Ini bagus jika Anda perlu mengirim seluruh direktori. Untuk satu file, jawaban Erik lebih sederhana.
Kelvin

1
@ Selvin: Tapi tar juga mempertahankan atribut dan nama file. Di antara yang lainnya itu berarti Anda hanya perlu mengetikkan nama satu kali (dan di sana Anda mendapatkan penyelesaian tab dari shell) Jadi saya akan mengatakan tar sebenarnya lebih sederhana, asalkan tar dipasang di wadah.
Maarten

1
The -f -adalah berlebihan sedikit meskipun, perilaku default adalah untuk menulis ke stdout pula.
Maarten

ini berarti ada ketergantungan host pada tar
cellige

Anda benar - Anda harus menginstal tar pada host dan di dalam container. Saat ini menggunakan docker cp adalah solusi yang lebih baik.
joemat

24

Untuk menyalin file dari host ke menjalankan wadah

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

Berdasarkan jawaban Erik dan komentar Mikl dan z0r.


Solusi yang diterima kadang-kadang mengganggu lekukan file ketika mentransfer ke menjalankan wadah. Ini berfungsi sempurna untuk kasus-kasus seperti itu
Mimpi


15

Ini adalah jawaban langsung untuk pertanyaan 'Menyalin file dari host ke wadah Docker' yang dimunculkan dalam pertanyaan ini dalam judul.

Coba docker cp. Ini adalah cara termudah untuk melakukan itu dan bekerja bahkan di Mac saya. Pemakaian:

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

Ini akan menyalin file some-file.txtdi direktori /rootpada mesin host Anda ke dalam wadah Docker yang dinamai some-docker-containerke dalam direktori /root. Sangat dekat dengan sintaks copy aman. Dan seperti yang ditunjukkan pada posting sebelumnya, Anda dapat menggunakannya sebaliknya. Yaitu, Anda juga menyalin file dari wadah ke host.

Dan sebelum Anda mengirim tautan ke bawah, silakan masukkan docker cp --help. Membaca dokumentasi bisa sangat membantu, kadang-kadang ...

Jika Anda tidak menyukai cara itu dan Anda ingin volume data dalam wadah yang sudah Anda buat dan jalankan, maka rekreasi adalah satu-satunya pilihan Anda hari ini. Lihat juga Bagaimana saya bisa menambahkan volume ke wadah Docker yang ada? .


15

Saya mencoba sebagian besar (upvoted) solusi di sini tetapi di buruh pelabuhan 17.09 (tahun 2018) tidak ada lagi folder / var / lib / docker / aufs.

Sederhana docker cpini menyelesaikan tugas ini.

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

Bagaimana cara mendapatkan nama_paket?

 docker ps 

Ada satu NAMESbagian. Jangan gunakan a IMAGE.


12

Untuk menyalin file / folder antara wadah dan sistem file lokal, ketikkan perintah:

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

Sebagai contoh,

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

Untuk mendapatkan id contianer, ketikkan perintah yang diberikan:

docker ps

Konten di atas diambil dari docker.com .


8

Dengan asumsi wadah sudah berjalan, ketikkan perintah yang diberikan:

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

Untuk berbagi file menggunakan direktori bersama, jalankan wadah dengan mengetikkan perintah yang diberikan:

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

Catatan: Masalah dengan izin mungkin muncul karena pengguna wadah tidak sama dengan pengguna host.


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

2
Perhatikan bahwa cattidak akan dihentikan setelah keluar. Jika itu penting bagi Anda (jika Anda menyalin skrip bash, bash akan menolak untuk menjalankannya), Anda harus menjalankan lsof | grep yourfilenamedan membunuh catproses yang menyimpan file tersebut.
johndodo

Terima kasih! Tip yang bagus. Bisakah Anda memberi tahu saya cara mematikan proses ini dengan satu perintah? Sesuatu seperti kill $(lsof | grep /path/to/file | sed ...). Saya akan berterima kasih atas bantuan Anda
Mikl

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

8

Ini adalah perintah untuk menyalin data dari Docker ke Host:

docker cp container_id:file path/filename /hostpath

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

Di bawah ini adalah perintah untuk menyalin data dari host ke buruh pelabuhan:

docker cp a.txt ccfbeb35116b:/home/

7

Di lingkungan buruh pelabuhan, semua kontainer ditemukan di direktori:

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

Untuk menyalin direktori sumber / file ke bagian mana pun dari wadah, ketikkan perintah yang diberikan:

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


5

tardan docker cpmerupakan kombo yang bagus untuk menyalin segala sesuatu dalam direktori.

Buat wadah volume data

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

Untuk mempertahankan hierarki direktori

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

Periksa pekerjaanmu

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

5

Jika host adalah CentOS atau Fedora, ada proxy TIDAK di /var/lib/docker/aufsdalamnya, tetapi berada di bawah /proc:

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

Cmd ini akan menyalin semua isi datadirektori ke /wadah dengan id "containerid".


Ini tidak unik untuk Redhat: ini juga bekerja pada Debian. (mungkin semua Gnu / Linux dengan /proc). Juga rentangkan path untuk meletakkan file di tempat lain, bukan hanya root.
ctrl-alt-delor

5

Dalam hal tidak jelas bagi orang seperti saya apa artinya mycontainerdi @ h3nrik jawab, itu sebenarnya id wadah. Untuk menyalin file WarpSquare.mp4dalam /app/example_scenes/1440p60dari wadah buruh pelabuhan keluar ke folder saat ini saya menggunakan ini.

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

di mana docker ps -q -lmenarik id wadah instance yang terakhir keluar. Dalam hal ini bukan wadah keluar Anda bisa mendapatkannya dengan docker container lsataudocker ps


1
Anda dapat membuat daftar id dari kontainer yang keluar dengan docker ps -aatau docker container ls -a.
0x7d7b

4

Banyak yang menemukan pertanyaan ini mungkin sebenarnya memiliki masalah menyalin file ke gambar Docker saat sedang dibuat (saya lakukan).

Dalam hal ini, Anda bisa menggunakan COPYperintah Dockerfileyang Anda gunakan untuk membuat gambar.

Lihat dokumentasi .


4

Anda bisa melacak alamat IP dari mesin lokal Anda menggunakan

ifconfig

Kemudian cukup masukkan ke dalam wadah Docker Anda dan ketik

scp user_name@ip_address:/path_to_the_file destination

Dalam kasus apa pun jika Anda tidak memiliki klien dan server SSH diinstal, cukup instal menggunakan:

sudo apt-get install openssh-server

Terima kasih banyak, itu bekerja dengan baik untuk saya. Plus, saya merasa lebih efisien daripada cara lain
user1314742

Ini adalah solusi yang mengerikan dalam hal keamanan.

4

Ini adalah onliner untuk menyalin satu file saat menjalankan wadah kucing jantan.

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

Ini akan menyalin file perang ke direktori webapps dan menjalankan aplikasi Anda dalam waktu singkat.


1
-v akan me-mount (yaitu membuat tautan), bukan menyalin
Vitaliy Ulantikov

perbedaan dalam hasilnya adalah pemasangan menyembunyikan konten kontainer sebelumnya, misalnya jika Anda memasang folder host pada folder kontainer Anda tidak dapat melihat lagi konten folder kontainer sebelumnya
mrq

4

Sintaks Penampung:

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

Dalam File buruh pelabuhan

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

3

Cara terbaik untuk menyalin file ke wadah yang saya temukan adalah memasang direktori pada host menggunakan -vopsi perintah docker run.


3

Ada jawaban yang bagus, tetapi terlalu spesifik. Saya menemukan docker pscara yang bagus untuk mendapatkan id kontainer yang Anda minati. Kemudian lakukan

mount | grep <id>

untuk melihat di mana volume terpasang. Itu

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

bagi saya, tetapi mungkin jalan yang berbeda tergantung pada OS dan konfigurasi. Sekarang cukup salin file ke jalur itu.

Penggunaan -vtidak selalu praktis.


3

Saya baru saja mulai menggunakan buruh pelabuhan untuk mengkompilasi VLC, inilah yang dapat Anda lakukan untuk menyalin file bolak-balik dari wadah:

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

Cari file yang dikenal di txt itu dan Anda akan memiliki folder, cd ke sana sebagai root dan voila! salin semua yang kamu inginkan.

Mungkin ada jalan dengan "digabung" di dalamnya, saya kira Anda ingin yang memiliki "diff" di dalamnya.

Juga jika Anda keluar dari wadah dan ingin kembali ke tempat terakhir Anda:

docker ps -a
docker start -i containerid

Saya kira itu berguna ketika Anda tidak menyebutkan nama dengan perintah seperti

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

Tentu metode hacker tapi terus kenapa!


3
docker cp SRC_PATH CONTAINER_ID:DEST_PATH

Sebagai contoh, saya ingin menyalin file saya xxxx / download / jenkins ke tomcat

Saya mulai mendapatkan id dari wadah 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

Metode favorit saya:

WADAH:

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

atau

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

jalur devicemapper tampaknya tidak berfungsi pada fedora dengan docker 1.6. Telah meletakkannya sebagai Q terpisah, stackoverflow.com/questions/29939419/... , komentar apa pun akan dihargai.
Yogesh_D

2

Menurut pendapat saya, Anda tidak harus menyalin file di dalam gambar tetapi Anda dapat menggunakan GIT atau SVN untuk file Anda dan kemudian mengatur volume yang disinkronkan dengan folder lokal. Gunakan skrip saat menjalankan wadah yang dapat memeriksa apakah data sudah ada di folder lokal jika tidak menyalinnya dari repositori GIT. Itu membuat gambar Anda sangat ringan.


Ini sepertinya risiko keamanan dan akses mimpi buruk yang menunggu untuk terjadi. Bagaimana Anda memberikan akses ke repositori git dari dalam gambar Anda? Bahkan dengan asumsi itu adalah repositori publik, Anda akan menganggap host yang digunakan wadah Anda memiliki akses ke repo itu.
tbm

Saya setuju dengan Anda jika git digunakan di dalam wadah buruh pelabuhan. Tetapi dalam kasus kami, skrip berjalan dari mesin host
h.aittamaa
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.