Docker kabının dosya sistemini keşfetme


651

Docker ile bir konteynerin içinde neler olduğunu veya orada hangi dosyaların olduğunu anlamam gerektiğini fark ettim. Bir örnek, docker dizininden görüntü indirmektir - görüntünün ne içerdiğine dair bir fikriniz yoktur, bu nedenle uygulamayı başlatmak imkansızdır.

İdeal olan, bunlara veya eşdeğeri ssh edebilmek. Bunu yapmak için bir araç var mı, yoksa bunu yapmam gerektiğini düşündüğümde docker'ı kavramsallaştırmam yanlış mı?


13
Docker son sürümlerinde, böyle bir şey mümkündür: docker exec <container> bash. Yani, kabın içinde bir kabuk açıyorsun.
dashohoxha

7
bir konteyner üzerinde bash çalıştırmak sadece bash kabın içine monte edilmişse çalışır
Christopher Thomas

7
Benzer şekilde şunları yapabilirsiniz: docker exec <container> ls <dir path>ve docker exec <container> cat <file path>. Ancak bash için -itseçenekleri ekleyin .
Noam Manos


3
@ChristopherThomas, kesinlikle. Bu nedenle bunu yapmanın tek sağlam yolunun docker image save image_name > image.tar@ Gaurav24'ün yanıtında belirtildiği gibi olduğunu gördüm.
Jaime Hablutzel

Yanıtlar:


737

GÜNCELLEME
En kolay yöntem: Docker exec'i kullanma

Docker sürüm 1.3 veya daha yeni bir sürümü execbenzer davranışı destekler nsenter. Bu komut, zaten çalışmakta olan kapsayıcıda yeni işlem çalıştırabilir (kapsayıcıda PID 1 işlemi zaten çalışıyor olmalıdır). /bin/bashKapsayıcı durumunu keşfetmek için çalışabilirsiniz :

docker exec -t -i mycontainer /bin/bash

bkz Docker komut satırı belgelere

Alternatif yöntem 1
Fotoğraf çekme

Kapsayıcı dosya sistemini şu şekilde değerlendirebilirsiniz:

# 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

Bu şekilde, çalışan konteynerin dosya sistemini tam zamanında değerlendirebilirsiniz. Kapsayıcı hala çalışıyor, gelecekteki değişiklikler dahil edilmedi.

Daha sonra kullanarak anlık görüntüyü silebilirsiniz (çalışan kabın dosya sistemi etkilenmez!):

docker rmi mysnapshot

Alternatif yöntem 2
ssh

Sürekli erişime ihtiyacınız varsa, sshd'yi kapınıza yükleyebilir ve sshd arka plan programını çalıştırabilirsiniz:

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

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

Bu şekilde, uygulamanızı ssh kullanarak çalıştırabilirsiniz (istediğinizi bağlayın ve yürütün).

GÜNCELLEME: Alternatif yöntem 3
merkez

Kullanın nsenter, bkz. Https://web.archive.org/web/20160305150559/http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/

Kısa sürüm: nsenter ile, bu kapsayıcı SSH veya herhangi bir özel amaçlı arka plan programı çalıştırmasa bile mevcut bir kapsayıcıya bir kabuk alabilirsiniz


6
ancak dosyalara erişmeniz gerekiyorsa "docker cp" komutunu kullanın. Kullanım: docker cp CONTAINER: PATH HOSTPATH ​​Kapsayıcı dosya sistemindeki dosyaları / klasörleri ana bilgisayar yoluna kopyalayın. Yollar, dosya sisteminin köküne göredir. #> docker cp 7bb0e258aefe: / etc / debian_version. #> docker cp blue_frog: / etc / hosts.
Amos Folarin

4
Seçenek 4, o kadar önemlidir ki üste taşınmalı ve yeniden adlandırılmalıdır Option 1.
automorphic

5
@JanusTroelsen Kabuk yoksa yükleyebilirsiniz - örneğin Alpin linux için dockerfile'da (ki aslında kabuğu yoktur): RUN apk update && apk add bash(boyut: ~ 4MB)
Kamil Kiełczewski 11:17

2
kendi tecrübelerime göre, Docker exec ile ilgili sınırlama, komutun çalışan bir kapsayıcıya veya bir tür giriş noktası olarak eklenmesi gerektiğidir. Dolayısıyla durdurulmuş bir kap bu yöntemin kapsamı dışındadır.
Webwoman

1
Window'un linux kabuğunu kullanmak içindocker exec -t -i mycontainer /bin/sh
Jason Masters

266

GÜNCELLEME: KEŞFET!

Bu komut, çalışan bir docker kapsayıcısını keşfetmenize izin vermelidir :

docker exec -it name-of-container bash

Bunun docker-compose içindeki karşılığı:

docker-compose exec web bash

(web bu durumda hizmetin adıdır ve varsayılan olarak tty'ye sahiptir.)

İçeri girdikten sonra:

ls -lsa

veya başka bir bash komutu:

cd ..

Bu komut bir docker görüntüsünü keşfetmenize izin vermelidir :

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

içeride bir kez yapmak:

ls -lsa

veya başka bir bash komutu:

cd ..

-itİnteraktif ... ve tty duruyor.


Bu komut, çalışan bir docker kapsayıcısını veya görüntüsünü incelemenize izin vermelidir :

docker inspect name-of-container-or-image

Bunu yapmak ve orada bashya da shiçinde olup olmadığını öğrenmek isteyebilirsiniz . Json dönüşünde giriş noktası veya cmd olup olmadığına bakın.

bkz liman işçisi exec belgeleri

bkz liman işçisi-oluşturma exec belgeleri

bkz belgeleri kontrol docker


1
Bu son derece yararlı, teşekkürler! Bir docker görüntü dosyası yapısında bulunan bir dosyayı sürükleyip bir uygulamaya bırakmam gerekiyor, ancak bir GUI biçiminde açılmadığı sürece bu mümkün olmayacak. Bu sorunu nasıl çözeceğime dair bir fikrin var mı?
Arkya Chatterjee

2
Bunun sadece bash yüklü bir kap üzerinde çalışacağı oldukça açık olmalıdır.
Yazılım Mühendisi

2
Bunu bir Windows Container / Powershell'de nasıl yapacağına bakan herkes için komut docker exec -ti <name> powershell( kaynak )
ssell

1
@ssell benim konteyner / görüntü bu yüzden docker exec -ti <name> cmdçalıştı bir nedenle powershell yoktu . Ve benim gibi diğer yeni başlayanlar için, docker psatadığınız okunabilir ad yerine kapsayıcı örneği adını (070494393ca5 gibi) kullandığınızdan emin olun .
Simon_Weaver

1
Görüntülerde ilişkin powershell github.com/aspnet/aspnet-docker/issues/362 - ve sadece pencere görüntülerde kıvrılıp gerekirse: blogs.technet.microsoft.com/virtualization/2017/12/19/...
Simon_Weaver

162

Durumunda kapsayıcınız (örn durdurulur veya bir kabuk yoktur hello-worldbelirtilen kurulum kılavuzu veya olmayan alpine traefik), bu muhtemelen dosya sistemini keşfetmek mümkündür yöntemdir.

Kabınızın dosya sistemini tar dosyasına arşivleyebilirsiniz:

docker export adoring_kowalevski > contents.tar

Veya dosyaları listeleyin:

docker export adoring_kowalevski | tar t

Görüntüye bağlı olarak biraz zaman ve disk alanı gerektirebileceğini unutmayın.


12
Standart UNIX araçları yüklü olmayan bir kabın içeriğini listelemek istedim. exportYukarıdaki örneğin bir çeşidi docker export adoring_kowalevski | tar tf -
olay yerine geldi

3
Dikkatsizliğe karşı bir uyarı: bu çok fazla veri dışa aktarabilir (> GB) ve uzun zaman alabilir.
Vince Bowdren

5
@berto, bu çok büyük bir şey değil, ama f -komutunuzun sonunda gerekmez , tar varsayılan olarak standart girdiden okur. Basitçe docker export adoring_kowalevski | tar tçalışır.
Shaun Bouckaert

Ne kadar basit o kadar iyi; harika, bahşiş için teşekkürler! 🙌🏽
berto

1
@ShaunBouckaert varsayılanı tar fkişinin yapılandırmasına bağlıdır. Bir kısmı TAPEortam değişkenidir. Diğerleri yapının bir parçası olarak kontrol edilir. Net etki, bir kişinin asla stdin okuduğunu veya stdout yazdığını varsaymamalı, ancak her zaman açıkça belirtmelidir.
roaima

42

Kapsayıcı dosya sistemi, docker'ın veri klasöründe, normalde / var / lib / docker'da bulunur. Çalışan bir kaplar dosya sistemini başlatmak ve incelemek için aşağıdakileri yapın:

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

Ve şimdi geçerli çalışma dizini kabın köküdür.


3
buna bağlı birimler dahil değildir.
hwjp

34

Konteyner Oluşturmadan Önce:

Kabın içine monte edilen görüntünün yapısını keşfetmek isterseniz,

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

Bu size bir görüntünün tüm katmanlarının görünürlüğünü ve json dosyalarında bulunan yapılandırmasını verir.

Kapsayıcı oluşturulduktan sonra:

Bunun için yukarıda zaten birçok cevap var. bunu yapmak için tercih ettiğim yol -

docker exec -t -i container /bin/bash


Burada, kabın içinde bash çalıştırmanın, yalnızca görüntü ile aynı mimariye sahip makinede yapıyorsanız işe yaradığı belirtilmelidir. Raspberry pi'nin görüntü dosya sistemine göz atmaya çalışan bir bilgisayardaysanız, bash hile çalışmaz.
Maxim Kulkin

@MaximKulkin Gerçekten mi? Kapsayıcı Linux ise, bash varsa, ana bilgisayarın ne olduğu önemli değildir. Belki de Windows kapsayıcılarını mı düşünüyorsunuz?
Thorbjørn Ravn Andersen

26

En çok oylanan cevap, kapsayıcı gerçekten başlatıldığında benim için çalışıyor, ancak çalıştırılması mümkün olmadığında ve örneğin dosyaları daha önce kaydettiğim kapsayıcıdan kopyalamak istediğinizde:

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

Docker cp ( link ) sayesinde, dosya sisteminizin başka bir parçası olduğu gibi doğrudan kapsayıcıdan kopyalayabilirsiniz. Örneğin, bir kap içindeki tüm dosyaları kurtarma:

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

Yinelemeli olarak kopyalamak istediğinizi belirtmeniz gerekmediğini unutmayın.


6
neden daha fazla + 1 yok! kesinlikle en iyi yol
Nicholas DiPiazza

Bu, tar üzerinden ihracat yapmaktan bile daha basit. Simgelerle dosyalara ulaşmak için -L kullanmak zorunda kaldım. Konteyneri çalıştırmaya gerek yok!
MKaama

17

On Ubuntu 14.04 çalıştıran Docker 1.3.1 , aşağıdaki dizinde ana makinede konteyner kök dosya sistemini bulundu:

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

Full Docker sürüm bilgileri:

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

Bir cazibe gibi çalışır: name = <name> dockerId = $ (docker incelemesi -f {{.Id}} $ name) / var / lib / docker / devicemapper / mnt / $ dockerId / rootfs /
Florent

3
Ubuntu 16.10 ve docker 1.12.1 ile bu maalesef artık böyle değil (hayır devicemapper dizin ). Dosya altında bulunur /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/.... Orada dosyalara erişmek için ne kadar taşınabilir / güvenli olduğundan emin değilim
WoJ

1
Docker, 1.10'dan itibaren, daha önce hem katman hem de konteyner tanımlayıcıları için olduğu gibi rastgele oluşturulmuş UUID kullanmayan yeni bir içerik adreslenebilir depolama modeli tanıttı. Yeni modelde, bunun yerine katman kimliği için güvenli bir içerik karması gelir. Yani bu yöntem artık çalışmayacak.
Artem Dolobanko

Bu taşınabilir değildir ve büyük ölçüde depolama sürücüsünün seçimine bağlıdır . Çözümün çalışıp çalışmayacağından emin değilimdirect-lvm örneğin .
rustyx

14

Kullanmayı deneyin

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

Bash'ın uygulanma olasılığı olabilir. bunun için kullanabilirsiniz

docker exec -it <container-name> sh

12

Ben aufs / devicemapper agnostik başka bir kirli hile kullanın.

Kap örneğin çalışıyor komutuna bakın ve docker ps bir apache veya javaben sadece aşağıdakileri yapın:

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

ve sen konteynerin içindesin.

Temel /proc/<PID>/root/olarak, bu işlem konteyner tarafından çalıştırıldığı sürece kök cd'yi klasöre ekleyebilirsiniz . Bu modu kullanarak sembollerin mantıklı olmayacağına dikkat edin.


Bu yöntem hakkında ek bilgi burada: superuser.com/a/1288058/195840
Eduardo Lucio

12

Kapsayıcınızın gerçek bir Linux sistemi olmaması dışında en çok oy verilen cevap iyidir.

Birçok konteynerin (özellikle go tabanlı) herhangi bir standart ikili (no /bin/bashveya /bin/sh) yoktur . Bu durumda, gerçek kapsayıcı dosyasına doğrudan erişmeniz gerekir:

Tıkır tıkır çalışıyor:

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

Not: Kök olarak çalıştırmanız gerekir.


Bu artık çalışmıyor. Devicemapper klasörü orada değil.
0xcaff

Eski cevapları olan insanların onları temizlemesi güzel olurdu
Matthew Purdon

2
Komutu yeni docker depolama yapısıyla eşleşecek şekilde güncelledim.
Florent

10

Benim durumumda kapta hiçbir kabuk desteklenmedi sh. Yani, bu bir cazibe gibi çalıştı

docker exec -it <container-name> sh


5

Bu, resim için bir bash oturumu başlatacaktır:

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


1
bu, varsayılan giriş
noktası

4

Benim için bu iyi çalışıyor ( / var / lib / docker / dizinini gösteren son yorumlar sayesinde ):

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

Burada, 2465790aa2c4 çalışan kabın kısa kimliğidir ( docker ps tarafından gösterildiği gibi ) ve ardından bir yıldızdır.


4

Docker'ın daha yeni sürümlerinde, kabınızın docker exec [container_name]içinde bir kabuk çalıştıran çalıştırabilirsiniz

Bir kaptaki tüm dosyaların bir listesini almak için çalıştırın docker exec [container_name] ls


1
Bunu denedim ve işe yaramadı. Khalil Gharbaoui'nin yukarıdaki önerisi işe yaradı.
Nick

Bu benim için çalıştı. Resim adı yerine kapsayıcı kimliğini de deneyebilirsiniz
Diwann

4

Docker aufs sürücüsü için:

Komut dosyası, konteyner kök dizinini bulur (Docker 1.7.1 ve 1.10.3'te test edin)

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

Mevcut cevapların hiçbiri, çıkmış (ve yeniden başlatılamayacak) ve / veya herhangi bir kabuğa sahip olmayan (örn. Dağıtımsız olanlar) bir kapsayıcısının durumunu ele almaz. Bu, Docker ana bilgisayarına kök erişiminiz olduğu sürece çalışır.

Gerçek bir manuel inceleme için önce katman kimliklerini bulun:

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

Çıktıda, şöyle bir şey görmelisiniz

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

Kapsayıcı dosya sisteminin geçerli görünür durumunu bulmak için bu klasöre (kök olarak) gidin.


3

Bu yanıt, konteyner çalışmıyor olsa bile docker birim dosya sistemini keşfetmek isteyenlere (benim gibi) yardımcı olacaktır.

Çalışan liman iş konteynırlarını listele:

docker ps

=> KONTEYNER KİMLİĞİ "4c721f1985bd"

Yerel fiziksel makinenizdeki docker birim bağlama noktalarına bakın ( https://docs.docker.com/engine/tutorials/dockervolumes/ ):

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

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

Bu bana yerel fiziksel makine dizini / tmp / container-garren komutunun / tmp docker birim hedefiyle eşlendiğini söyler.

Yerel fiziksel makine dizinini (/ tmp / container-garren) bilmek, docker konteynerinin çalışıp çalışmadığını dosya sistemini keşfedebileceğim anlamına gelir. Bu, konteyner çalışmadığı zaman bile devam etmemesi gereken bazı artık veriler olduğunu anlamama yardımcı olmak için kritikti.


1
Bu, yalnızca kapsayıcıya birim olarak bağlanan ancak kapsayıcının tüm dosya sistemine erişilmesine izin vermeyen bir yerel dizin bulur.
Bojan Komazec

3

başka bir hile atom aracı kullanmak gibi bir şey yapmaktır:

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

Docker görüntüsü incelemeniz için / path / to / mnt dizinine bağlanır .


Ancak bunun çalışması için özel olarak yapılmış kaplara sahip olmanız gerekiyor, değil mi? Belki bunu bir uyarı olarak eklemelisiniz, çünkü çoğu insan onu bir çözüm olarak takımlarına / şirketlerine
satamaz

3

Sadece LINUX için

Kullandığım en basit yol, docker konteyner dosyalarını incelemek için konteynır olan proc dir kullanmaktı.

  1. Kapsayıcı işlem kimliğini (PID) bulun ve bazı değişkenlerde saklayın

    PID = $ (liman işçisi -f '{{.State.Pid}}' konteynır-adınızı-burayı denetler)

  2. Kapsayıcı işleminin çalıştığından emin olun ve kapsayıcı klasörüne girmek için name değişkenini kullanın

    cd / proc / $ PID / kök

Sadece bu uzun komutu kullanarak PID numarasını bulmadan direk almak istiyorsanız

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

İpuçları:

Kabın içine girdikten sonra, yaptığınız her şey, hizmetin durdurulması veya bağlantı noktası numarasının değiştirilmesi gibi kabın gerçek sürecini etkiler.

Umarım yardımcı olur

Not:

Bu yöntem yalnızca kap hala çalışıyorsa çalışır, aksi takdirde kap durmuş veya kaldırılmışsa dizin artık mevcut olmaz


2

Konteynerin içinde neler olduğunu anlamak için tercih ettiğim yol:

  1. maruz -p 8000

    docker run -it -p 8000:8000 image
    
  2. İçindeki sunucuyu başlat

    python -m SimpleHTTPServer
    

2

Zaten çalışan bir kapsayıcı için şunları yapabilirsiniz:

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

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

Bu dizine cd yazmak için root olmanız gerekir. Kök değilseniz, komutu çalıştırmadan önce 'sudo su' deneyin.

Düzenleme: v1.3, Jiri'nin cevabına bakınız - daha iyidir.


4
Ben bir kabuk başlatan başka bir suid programı başlatan bir suid programı çalıştırmak için çok az nedeni var çünkü "sudo su" yerine "sudo -i" için kısmi. Orta adamı kesin. :)
dannysauer

Cevabınız çok iyi, sadece yol değil. Piercebot'un yolunu kullanmalısınız.
Florent

2

Docker v19.03 kullanıyorsanız, aşağıdaki adımları izleyin.

# 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

AUFS depolama sürücüsünü kullanıyorsanız, herhangi bir kabın dosya sistemi kökünü (mnt) ve readwrite katmanını bulmak için docker katmanı betiğimi kullanabilirsiniz :

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

Edit 2018-03-28: Docker
katmanı Docker -backup ile değiştirildi


1

docker execKomut birden durumlarda yardımcı olabilecek bir çalışan kapta bir komutu çalıştırmak için.

Kullanım: docker exec [SEÇENEKLER] KONTEYNER KOMUTANLIĞI [ARG ...]

Çalışan bir kapsayıcıda komut çalıştırma

Seçenekler:
  -d, --detach Müstakil mod: arka planda komut çalıştır
      --detach-keys string Bir ayırmak için anahtar sırasını geçersiz kıl
                             konteyner
  -e, --env list Ortam değişkenlerini ayarlama
  -i, - etkileşimli Bağlı olmasa bile STDIN'i açık tutun
      --privileged Komuta genişletilmiş ayrıcalıklar verme
  -t, --tty Sözde bir TTY ayır
  -u, --kullanıcı dizesi Kullanıcı adı veya UID (biçim:
                             [:])
  -w, --workdir string Kapsayıcı içindeki çalışma dizini

Örneğin :

1) Çalışan kapsayıcı dosya sistemine bash'de erişim:

docker exec -it containerId bash 

2) Gerekli haklara sahip olabilmek için çalışan konteyner dosya sistemine kök olarak erişmek:

docker exec -it -u root containerId bash  

Bu, bir kapta kök olarak bazı işlemler yapabilmek için özellikle yararlıdır.

3) Belirli bir çalışma diziniyle çalışan kapsayıcı dosya sistemine bash'de erişim:

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

0

Konteynerin içinde bir bash çalıştırabilirsiniz: $ docker run -it ubuntu /bin/bash

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.