Menjelajahi sistem file Docker


652

Saya perhatikan dengan buruh pelabuhan bahwa saya perlu memahami apa yang terjadi di dalam wadah atau file apa yang ada di sana. Salah satu contohnya adalah mengunduh gambar dari indeks buruh pelabuhan - Anda tidak memiliki petunjuk tentang isi gambar sehingga tidak mungkin untuk memulai aplikasi.

Apa yang ideal adalah untuk dapat ssh ke mereka atau setara. Apakah ada alat untuk melakukan ini, atau konsep saya tentang buruh pelabuhan salah dalam berpikir saya harus bisa melakukan ini.


13
Dalam versi terbaru dari Docker, sesuatu seperti ini mungkin: docker exec <container> bash. Jadi, Anda hanya membuka cangkang di dalam wadah.
dashohoxha

7
menjalankan bash pada sebuah wadah hanya berfungsi jika bash dipasang di dalam wadah
Christopher Thomas

7
Demikian pula, Anda dapat melakukan: docker exec <container> ls <dir path>dan docker exec <container> cat <file path>. Namun untuk bash, tambahkan -itopsi.
Noam Manos


3
@ChristopherThomas, tepatnya. Karena itu saya telah menemukan bahwa satu-satunya cara yang kuat untuk melakukan ini adalah dengan docker image save image_name > image.tarsebagaimana ditunjukkan dalam respons dari @ Gaurav24.
Jaime Hablutzel

Jawaban:


737

PEMBARUAN
Metode termudah: Menggunakan docker exec

Docker versi 1.3 atau yang lebih baru mendukung perintah execyang berperilaku mirip dengan nsenter. Perintah ini dapat menjalankan proses baru dalam wadah yang sudah berjalan (wadah harus sudah menjalankan proses PID 1). Anda dapat berlari /bin/bashuntuk menjelajahi keadaan wadah:

docker exec -t -i mycontainer /bin/bash

lihat dokumentasi baris perintah Docker

Metode alternatif 1
Snapshotting

Anda dapat mengevaluasi sistem file kontainer dengan cara ini:

# find ID of your running container:
docker ps

# create image (snapshot) from container filesystem
docker commit 12345678904b5 mysnapshot

# explore this filesystem using bash (for example)
docker run -t -i mysnapshot /bin/bash

Dengan cara ini, Anda dapat mengevaluasi sistem file wadah yang sedang berjalan pada saat yang tepat. Kontainer masih berjalan, tidak ada perubahan di masa depan yang disertakan.

Anda nanti dapat menghapus snapshot menggunakan (filesystem wadah yang sedang berjalan tidak terpengaruh!):

docker rmi mysnapshot

Metode alternatif 2
ssh

Jika Anda memerlukan akses terus menerus, Anda dapat menginstal sshd ke wadah Anda dan menjalankan daemon sshd:

 docker run -d -p 22 mysnapshot /usr/sbin/sshd -D

 # you need to find out which port to connect:
 docker ps

Dengan cara ini, Anda dapat menjalankan aplikasi menggunakan ssh (hubungkan dan jalankan apa yang Anda inginkan).

UPDATE: Alternatif metode 3
nsenter

Gunakan nsenter, lihat https://web.archive.org/web/20160305150559/http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/

Versi singkatnya adalah: dengan nsenter, Anda bisa mendapatkan shell ke wadah yang sudah ada, bahkan jika wadah itu tidak menjalankan SSH atau jenis daemon tujuan khusus apa pun


6
tetapi perhatikan jika Anda memerlukan akses ke file menggunakan perintah "docker cp" Penggunaan: docker cp CONTAINER: PATH HOSTPATH ​​Menyalin file / folder dari sistem file container ke jalur host. Path relatif terhadap root sistem file. #> buruh pelabuhan cp 7bb0e258aefe: / etc / debian_version. #> buruh pelabuhan cp blue_frog: / etc / hosts.
Amos Folarin

4
Opsi 4 sangat penting sehingga harus dipindahkan ke atas dan diganti namanya Option 1.
automorfik

5
@JanusTroelsen Jika tidak ada shell, Anda dapat menginstalnya - misalnya di dockerfile untuk linux alpine (yang memang tidak memiliki shell) dengan: RUN apk update && apk add bash(ukuran: ~ 4MB)
Kamil Kiełczewski

2
pada pengalaman saya sendiri, batasan dengan Docker exec adalah bahwa perintah harus ditambahkan pada wadah yang sedang berjalan atau sebagai semacam entrypoint. Oleh karena itu wadah yang berhenti berada di luar jangkauan metode ini.
Webwoman

1
Untuk menggunakan cangkang linux Windowdocker exec -t -i mycontainer /bin/sh
Jason Masters

266

PEMBARUAN: MENJELAJAHI!

Perintah ini memungkinkan Anda menjelajahi wadah buruh pelabuhan yang sedang beroperasi :

docker exec -it name-of-container bash

Persamaan untuk ini dalam komposisi buruh pelabuhan adalah:

docker-compose exec web bash

(web adalah nama layanan dalam kasus ini dan memiliki tty secara default.)

Setelah Anda berada di dalam, lakukan:

ls -lsa

atau perintah bash lainnya seperti:

cd ..

Perintah ini memungkinkan Anda menjelajahi gambar buruh pelabuhan :

docker run --rm -it --entrypoint=/bin/bash name-of-image

sekali di dalam do:

ls -lsa

atau perintah bash lainnya seperti:

cd ..

The -itsingkatan interaktif ... dan tty.


Perintah ini harus memungkinkan Anda memeriksa wadah buruh pelabuhan atau gambar :

docker inspect name-of-container-or-image

Anda mungkin ingin melakukan ini dan mencari tahu apakah ada bashatau shdi sana. Cari entrypoint atau cmd di json return.

lihat dokumentasi exec buruh pelabuhan

lihat dokumentasi exec buruh pelabuhan

lihat buruh pelabuhan memeriksa dokumentasi


1
Ini sangat berguna, terima kasih! Saya perlu menyeret dan meletakkan file yang ada di dalam struktur file gambar buruh pelabuhan ke dalam aplikasi, tetapi itu tidak akan mungkin terjadi kecuali dibuka dalam format GUI. Adakah ide bagaimana saya bisa mengatasinya?
Arkya Chatterjee

2
Seharusnya cukup jelas bahwa ini hanya akan bekerja pada wadah yang telah menginstal bash.
Insinyur Perangkat Lunak

2
Bagi siapa pun yang mencari cara melakukan ini pada Windows Container / Powershell, perintahnya adalah docker exec -ti <name> powershell( sumber )
ssell

1
@ssell wadah / gambar saya tidak memiliki PowerShell karena beberapa alasan jadi docker exec -ti <name> cmdberfungsi. Dan untuk pemula lain seperti saya pastikan untuk menggunakan nama instance wadah dari docker ps(sesuatu seperti 070494393ca5) daripada nama yang dapat dibaca yang Anda tetapkan.
Simon_Weaver

1
tentang PowerShell dalam gambar github.com/aspnet/aspnet-docker/issues/362 - dan jika Anda hanya perlu meringkuk di jendela gambar: blogs.technet.microsoft.com/virtualization/2017/12/19/...
Simon_Weaver

162

Jika wadah Anda dihentikan atau tidak memiliki cangkang (misalnya hello-worlddisebutkan dalam panduan instalasi , atau bukan alpine traefik), ini mungkin satu-satunya metode yang mungkin untuk menjelajahi sistem file.

Anda dapat mengarsipkan sistem file wadah Anda ke file tar:

docker export adoring_kowalevski > contents.tar

Atau daftar file:

docker export adoring_kowalevski | tar t

Perhatikan, bahwa tergantung pada gambar, mungkin butuh waktu dan ruang disk.


12
Saya hanya ingin daftar isi wadah yang tidak memiliki alat UNIX standar diinstal. Variasi dari exportcontoh di atas menyentuh titik:docker export adoring_kowalevski | tar tf -
berto

3
Peringatan untuk yang tidak waspada: ini mungkin mengekspor banyak data (> GB) dan membutuhkan waktu lama.
Vince Bowdren

5
@to tidak berarti itu adalah hal yang besar, tetapi Anda tidak perlu memerlukan f -di akhir perintah Anda, tar membaca dari input standar secara default. Cukup docker export adoring_kowalevski | tar tberhasil.
Shaun Bouckaert

Semakin sederhana semakin baik; luar biasa, terima kasih atas tipnya! 🙌🏽
berto

1
@ShaunBouckaert, default untuk tar fbergantung pada konfigurasi seseorang. Satu bagian adalah TAPEvariabel lingkungan. Yang lain dikendalikan sebagai bagian dari bangunan. Efek bersihnya adalah bahwa seseorang tidak boleh menganggap itu membaca stdin atau menulis stdout tetapi selalu menyatakannya secara eksplisit.
roaima

42

Sistem file wadah ada di folder data buruh pelabuhan, biasanya di / var / lib / docker. Untuk memulai dan memeriksa sistem file kontainer yang berjalan, lakukan hal berikut:

hash=$(docker run busybox)
cd /var/lib/docker/aufs/mnt/$hash

Dan sekarang direktori kerja saat ini adalah akar dari wadah.


3
ini tidak akan termasuk volume yang terpasang.
hwjp

34

Sebelum Pembuatan Wadah:

Jika Anda menjelajahi struktur gambar yang dipasang di dalam wadah, Anda bisa melakukannya

sudo docker image save image_name > image.tar
tar -xvf image.tar

Ini akan memberi Anda visibilitas semua lapisan gambar dan konfigurasinya yang hadir dalam file json.

Setelah pembuatan wadah:

Untuk ini sudah ada banyak jawaban di atas. cara pilihan saya untuk melakukan ini adalah -

docker exec -t -i container /bin/bash


Harus disebutkan di sini bahwa menjalankan bash di dalam wadah hanya berfungsi jika Anda melakukannya pada mesin dengan arsitektur yang sama dengan gambar. Jika Anda menggunakan PC yang mencoba mengintip sistem file gambar raspberry pi, trik bash tidak akan berfungsi.
Maxim Kulkin

@ MaximKulkin Benarkah? Jika wadahnya adalah Linux, tidak peduli apa hostnya, jika bash tersedia. Mungkin Anda memikirkan wadah Windows?
Thorbjørn Ravn Andersen

26

Jawaban yang paling banyak dipilih adalah bekerja untuk saya ketika wadah benar-benar dimulai, tetapi ketika itu tidak mungkin dijalankan dan Anda misalnya ingin menyalin file dari wadah ini telah menyelamatkan saya sebelumnya:

docker cp <container-name>:<path/inside/container> <path/on/host/>

Berkat docker cp ( tautan ) Anda dapat menyalin langsung dari wadah karena itu adalah bagian lain dari sistem file Anda. Misalnya, memulihkan semua file di dalam sebuah wadah:

mkdir /tmp/container_temp
docker cp example_container:/ /tmp/container_temp/

Perhatikan bahwa Anda tidak perlu menentukan bahwa Anda ingin menyalin secara rekursif.


6
mengapa ini tidak memiliki lebih banyak +1! pasti cara terbaik
Nicholas DiPiazza

Ini bahkan lebih sederhana daripada mengekspor melalui tar. Saya harus menggunakan -L untuk mendapatkan file melalui symlink. Tidak perlu menjalankan wadah!
MKaama

17

Pada Ubuntu 14.04 menjalankan Docker 1.3.1 , saya menemukan filesystem root kontainer pada mesin host di direktori berikut:

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

Informasi versi Docker lengkap:

Client version: 1.3.1
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 4e9bbfa
OS/Arch (client): linux/amd64
Server version: 1.3.1
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 4e9bbfa

Bekerja seperti pesona: name = <name> dockerId = $ (buruh pelabuhan memeriksa -f {{.Id}} $ name) / var / lib / docker / devicemapper / mnt / $ dockerId / rootfs /
Florent

3
Dengan Ubuntu 16.10 dan docker 1.12.1 ini sayangnya tidak lagi terjadi (tidak ada devicemapperdirektori). File ada di bawah /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/.... Saya tidak yakin seberapa portabel / amannya mengakses file di sana
WoJ

1
Mulai dari 1.10, Docker memperkenalkan model penyimpanan konten yang dapat dialamatkan baru, yang tidak menggunakan UUID yang dibuat secara acak, seperti sebelumnya baik untuk pengidentifikasi lapisan dan wadah. Dalam model baru ini diganti dengan hash konten aman untuk id lapisan. Jadi metode ini tidak akan berfungsi lagi.
Artem Dolobanko

Ini tidak portabel dan sangat tergantung pada pilihan driver penyimpanan . Tidak yakin apakah solusinya akan berfungsi direct-lvmmisalnya.
rustyx

14

Coba gunakan

docker exec -it <container-name> /bin/bash

Mungkin ada kemungkinan bash tidak diterapkan. untuk itu bisa kamu gunakan

docker exec -it <container-name> sh

12

Saya menggunakan trik kotor lain yaitu aufs / devicemapper agnostic.

Saya melihat perintah bahwa wadah berjalan misalnya docker ps dan jika itu adalah apache atau javasaya hanya melakukan hal berikut:

sudo -s
cd /proc/$(pgrep java)/root/

dan kau ada di dalam wadah.

Pada dasarnya Anda dapat me-root cd ke /proc/<PID>/root/folder selama proses itu dijalankan oleh kontainer. Waspadalah symlink tidak akan masuk akal menggunakan mode itu.


Informasi tambahan tentang metode ini di sini: superuser.com/a/1288058/195840
Eduardo Lucio

12

Jawaban yang paling banyak dipilih adalah baik kecuali jika wadah Anda bukan sistem Linux yang sebenarnya.

Banyak kontainer (terutama yang berbasis go) tidak memiliki biner standar (tidak /bin/bashatau /bin/sh). Dalam hal ini, Anda perlu mengakses file kontainer yang sebenarnya secara langsung:

Bekerja seperti pesona:

name=<name>
dockerId=$(docker inspect -f {{.Id}} $name)
mountId=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$dockerId/mount-id)
cd /var/lib/docker/aufs/mnt/$mountId

Catatan: Anda harus menjalankannya sebagai root.


Ini tidak lagi berfungsi. Folder devicemapper tidak ada di sana.
0xcaff

Alangkah baiknya jika orang-orang dengan jawaban yang sudah ketinggalan zaman akan membersihkannya
Matthew Purdon

2
Saya memperbarui perintah untuk mencocokkan struktur penyimpanan buruh pelabuhan baru.
Florent

10

Dalam kasus saya tidak ada cangkang didukung dalam wadah kecuali sh. Jadi, ini bekerja seperti pesona

docker exec -it <container-name> sh


5

Ini akan meluncurkan sesi bash untuk gambar:

run docker --rm -it --entrypoint = / bin / bash


1
ini berguna ketika titik masuk default tidak berjalan
parsethis

4

Bagi saya, ini berfungsi dengan baik (berkat komentar terakhir untuk menunjukkan direktori / var / lib / docker / ):

chroot /var/lib/docker/containers/2465790aa2c4*/root/

Di sini, 2465790aa2c4 adalah ID pendek dari wadah yang sedang berjalan (seperti yang ditampilkan oleh buruh pelabuhan ps ), diikuti oleh bintang.


4

Pada versi Docker yang lebih baru Anda dapat menjalankan docker exec [container_name]yang menjalankan shell di dalam wadah Anda

Jadi untuk mendapatkan daftar semua file dalam suatu wadah jalankan saja docker exec [container_name] ls


1
Saya mencoba ini dan tidak berhasil. Saran Khalil Gharbaoui di atas berhasil.
Nick

Itu berhasil bagi saya. Anda juga dapat mencoba dengan id wadah alih-alih nama gambar
Diwann

4

Untuk driver buruh pelabuhan:

Script akan menemukan direktori root kontainer (Tes pada buruh pelabuhan 1.7.1 dan 1.10.3)

if [ -z "$1" ] ; then
 echo 'docker-find-root $container_id_or_name '
 exit 1
fi
CID=$(docker inspect   --format {{.Id}} $1)
if [ -n "$CID" ] ; then
    if [ -f  /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id ] ; then
        F1=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id)
       d1=/var/lib/docker/aufs/mnt/$F1
    fi
    if [ ! -d "$d1" ] ; then
        d1=/var/lib/docker/aufs/diff/$CID
    fi
    echo $d1
fi

4

Tidak satu pun dari jawaban yang ada menangani wadah yang keluar (dan tidak dapat dimulai kembali) dan / atau tidak memiliki shell yang terpasang (mis. Yang tidak distro). Yang ini berfungsi selama Anda memiliki akses root ke host Docker.

Untuk inspeksi manual nyata, cari tahu ID lapisan pertama:

docker inspect my-container | jq '.[0].GraphDriver.Data'

Dalam output, Anda akan melihat sesuatu seperti

"MergedDir": "/var/lib/docker/overlay2/03e8df748fab9526594cfdd0b6cf9f4b5160197e98fe580df0d36f19830308d9/merged"

Arahkan ke folder ini (sebagai root) untuk menemukan keadaan sistem file kontainer yang terlihat saat ini.


3

Jawaban ini akan membantu mereka (seperti saya) yang ingin menjelajahi sistem file volume buruh pelabuhan bahkan jika wadah tidak berjalan.

Daftar wadah buruh pelabuhan yang sedang beroperasi:

docker ps

=> ID KONTAINER "4c721f1985bd"

Lihatlah titik pemasangan volume buruh pelabuhan di mesin fisik lokal Anda ( https://docs.docker.com/engine/tutorials/dockervolumes/ ):

docker inspect -f {{.Mounts}} 4c721f1985bd

=> [{/ tmp / container-garren / tmp true rprivate}]

Ini memberitahu saya bahwa direktori mesin fisik lokal / tmp / container-garren dipetakan ke / volume tujuan docker docker.

Mengetahui direktori mesin fisik lokal (/ tmp / container-garren) berarti saya dapat menjelajahi filesystem apakah wadah buruh pelabuhan berjalan atau tidak. Ini penting untuk membantu saya mengetahui bahwa ada beberapa data residual yang seharusnya tidak bertahan bahkan setelah wadah tidak berjalan.


1
Ini hanya menemukan direktori lokal yang dipasang sebagai volume di dalam wadah tetapi tidak memungkinkan mengakses seluruh sistem file penampung.
Bojan Komazec

3

Trik lain adalah dengan menggunakan alat atom untuk melakukan sesuatu seperti:

mkdir -p /path/to/mnt && atomic mount IMAGE /path/to/mnt

Gambar Docker akan dipasang ke / path / ke / mnt untuk Anda memeriksanya.


Tetapi Anda harus memiliki wadah yang dibuat khusus agar ini berfungsi, bukan? Mungkin Anda harus menambahkannya sebagai peringatan, karena kebanyakan orang tidak akan dapat menjualnya kepada tim / perusahaan mereka sebagai solusi ...
Angelos Pikoulas

3

Hanya untuk LINUX

Cara paling sederhana yang saya gunakan adalah menggunakan proc, yang merupakan wadah harus dijalankan untuk memeriksa file kontainer buruh pelabuhan.

  1. Cari tahu id proses (PID) dari wadah dan simpan ke dalam beberapa variabel

    PID = $ (buruh pelabuhan memeriksa -f '{{.State.Pid}}' nama-wadah-Anda-di sini)

  2. Pastikan proses penampung berjalan, dan gunakan nama variabel untuk masuk ke folder penampung

    cd / proc / $ PID / root

Jika Anda ingin melewati dir tanpa mengetahui nomor PID hanya dengan menggunakan perintah panjang ini

cd /proc/$(docker inspect -f '{{.State.Pid}}' your-container-name-here)/root

Kiat:

Setelah Anda masuk ke dalam wadah, semua yang Anda lakukan akan memengaruhi proses aktual wadah tersebut, seperti menghentikan layanan atau mengubah nomor port.

Semoga ini bisa membantu

catatan:

Metode ini hanya berfungsi jika wadah masih berjalan, jika tidak direktori tidak akan ada lagi jika wadah sudah berhenti atau dihapus


2

Cara pilihan saya untuk memahami apa yang terjadi di dalam wadah adalah:

  1. mengekspos -p 8000

    docker run -it -p 8000:8000 image
    
  2. Mulai server di dalamnya

    python -m SimpleHTTPServer
    

2

Untuk wadah yang sudah berjalan, Anda dapat melakukan:

dockerId=$(docker inspect -f {{.Id}} [docker_id_or_name])

cd /var/lib/docker/btrfs/subvolumes/$dockerId

Anda harus menjadi root untuk melakukan cd ke dir itu. Jika Anda tidak root, coba 'sudo su' sebelum menjalankan perintah.

Sunting: Mengikuti v1.3, lihat jawaban Jiri - lebih baik.


4
Saya sangat setuju dengan "sudo -i" daripada "sudo su" karena ada sedikit alasan untuk menjalankan program suid yang meluncurkan program suid lain yang meluncurkan shell. Hentikan perantara. :)
dannysauer

Jawaban Anda sangat bagus, hanya jalannya tidak. Anda harus menggunakan jalur piercebot.
Florent

2

Jika Anda menggunakan Docker v19.03, Anda ikuti langkah-langkah di bawah ini.

# find ID of your running container:

  docker ps

# create image (snapshot) from container filesystem

  docker commit 12345678904b5 mysnapshot

# explore this filesystem 

  docker run -t -i mysnapshot /bin/sh

1

Jika Anda menggunakan driver penyimpanan AUFS, Anda dapat menggunakan skrip docker-layer saya untuk menemukan root sistem file (mnt) kontener dan baca-tulis layer:

# docker-layer musing_wiles
rw layer : /var/lib/docker/aufs/diff/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f
mnt      : /var/lib/docker/aufs/mnt/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f

Sunting 2018-03-28:
docker-layer telah digantikan oleh docker-backup


1

The docker execperintah untuk menjalankan perintah dalam wadah berjalan dapat membantu dalam beberapa kasus.

Penggunaan: docker exec [OPTIONS] CONTAINER COMMAND [ARG ...]

Jalankan perintah dalam wadah yang berjalan

Pilihan:
  -d, --detach Detached mode: jalankan perintah di latar belakang
      --detach-keys string Mengganti urutan kunci untuk melepaskan a
                             wadah
  -e, --env list Menetapkan variabel lingkungan
  -i, --interactive Tetap buka STDIN walaupun tidak terpasang
      --privileged Berikan hak istimewa yang diperluas untuk perintah
  -t, --tty Mengalokasikan pseudo-TTY
  -u, --user string Username atau UID (format:
                             [:])
  -w, --workdir string Direktori kerja di dalam wadah

Sebagai contoh :

1) Mengakses secara bash ke sistem file container yang sedang berjalan:

docker exec -it containerId bash 

2) Mengakses secara bash ke sistem file container yang sedang berjalan sebagai root untuk dapat memiliki hak yang diperlukan:

docker exec -it -u root containerId bash  

Ini sangat berguna untuk dapat melakukan beberapa pemrosesan sebagai root di wadah.

3) Mengakses secara bash ke sistem file kontainer yang sedang berjalan dengan direktori kerja tertentu:

docker exec -it -w /var/lib containerId bash 

0

Anda dapat menjalankan bash di dalam wadah dengan ini: $ docker run -it ubuntu /bin/bash

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.