Eksplorowanie systemu plików kontenera Docker

651

Za pomocą okna dokowanego zauważyłem, że muszę zrozumieć, co dzieje się w kontenerze lub jakie pliki tam są. Jednym z przykładów jest pobieranie obrazów z indeksu dokowania - nie masz pojęcia, co zawiera obraz, więc uruchomienie aplikacji jest niemożliwe.

Idealne byłoby, aby móc w nich ssh lub równorzędnie. Czy istnieje na to narzędzie, czy też moja konceptualizacja dokera jest błędna w myśleniu, że powinienem to zrobić.

użytkownik2668128
źródło
13
W najnowszych wersjach Döcker, coś takiego jest możliwe: docker exec <container> bash. Po prostu otwórz skorupę w pojemniku.
dashohoxha
7
uruchomienie bash na kontenerze działa tylko wtedy, gdy bash jest zainstalowany w kontenerze
Christopher Thomas
7
Podobnie możesz zrobić: docker exec <container> ls <dir path>i docker exec <container> cat <file path>. Jednak dla bash dodaj -itopcje.
Noam Manos,
3
@ChristopherThomas, dokładnie. Z tego powodu odkryłem, że jedynym solidnym sposobem na to jest docker image save image_name > image.tarjak wskazano w odpowiedzi z @ Gaurav24.
Jaime Hablutzel

Odpowiedzi:

736

AKTUALIZACJA
Najłatwiejsza metoda: za pomocą exec docker

Docker w wersji 1.3 lub nowszej obsługuje polecenie execzachowujące się podobnie nsenter. Ta komenda może uruchomić nowy proces w już działającym kontenerze (kontener musi już mieć uruchomiony proces PID 1). Możesz uruchomić, /bin/bashaby zbadać stan kontenera:

docker exec -t -i mycontainer /bin/bash

zobacz dokumentację wiersza polecenia Docker

Alternatywna metoda 1
Migawka

Możesz ocenić system plików kontenera w ten sposób:

# 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

W ten sposób możesz ocenić system plików uruchomionego kontenera w dokładnym momencie. Kontener nadal działa, nie uwzględnia się przyszłych zmian.

Możesz później usunąć migawkę za pomocą (nie ma to wpływu na system plików uruchomionego kontenera!):

docker rmi mysnapshot

Alternatywna metoda 2
ssh

Jeśli potrzebujesz ciągłego dostępu, możesz zainstalować sshd w kontenerze i uruchomić demona sshd:

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

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

W ten sposób możesz uruchomić aplikację za pomocą ssh (podłącz i uruchom co chcesz).

AKTUALIZACJA: Alternatywna metoda 3
nsenter

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

Krótka wersja to: za pomocą nsenter można wprowadzić powłokę do istniejącego kontenera, nawet jeśli ten kontener nie obsługuje SSH ani żadnego innego demona specjalnego przeznaczenia

Jiri
źródło
6
ale uwaga: jeśli potrzebujesz dostępu do plików, użyj polecenia „docker cp” Zastosowanie: docker cp POJEMNIK: ŚCIEŻKA ŚCIEŻKI Skopiuj pliki / foldery z systemu plików kontenerów na ścieżkę hosta. Ścieżki są względne w stosunku do katalogu głównego systemu plików. #> docker cp 7bb0e258aefe: / etc / debian_version. #> docker cp blue_frog: / etc / hosts.
Amos Folarin
4
Opcja 4 jest tak ważna, że ​​należy ją przenieść na szczyt i zmienić jej nazwę Option 1.
automorficzny
5
@JanusTroelsen Jeśli nie ma powłoki, możesz ją zainstalować - na przykład w pliku dokującym dla alpejskiego linuxa (który tak naprawdę nie ma powłoki) przez: RUN apk update && apk add bash(rozmiar: ~ 4 MB)
Kamil Kiełczewski
2
z własnego doświadczenia wynika, że ​​w Docker exec ograniczeniem jest to, że polecenie musi być dodane do działającego kontenera lub jako rodzaj punktu wejścia. Dlatego zatrzymany pojemnik nie wchodzi w zakres tej metody.
Webwoman
1
Aby użyć powłoki linuksowej systemu Windowsdocker exec -t -i mycontainer /bin/sh
Jason Masters
266

AKTUALIZACJA: ODKRYWANIE!

To polecenie powinno umożliwić eksplorację działającego kontenera dokowanego :

docker exec -it name-of-container bash

Odpowiednikiem tego w docker-compose byłoby:

docker-compose exec web bash

(web jest nazwą usługi w tym przypadku i domyślnie ma tty).

Kiedy już będziesz w środku:

ls -lsa

lub dowolne inne polecenie bash, takie jak:

cd ..

To polecenie powinno umożliwić eksplorację obrazu dokera :

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

w środku wykonaj:

ls -lsa

lub dowolne inne polecenie bash, takie jak:

cd ..

-itOznacza interaktywnej ... a tty.


To polecenie powinno umożliwić sprawdzenie działającego kontenera lub obrazu dokowanego :

docker inspect name-of-container-or-image

Możesz to zrobić i dowiedzieć się, czy jest tam bashczy shtam. Poszukaj punktu wejścia lub cmd w zwrocie JSON.

patrz dokumentacja exec dokera

zobacz dokumentację exec-docker-compose

patrz doker inspekcji dokumentacji

Khalil Gharbaoui
źródło
1
To bardzo przydatne, dzięki! Muszę przeciągnąć i upuścić plik zawarty w strukturze pliku obrazu dokera do aplikacji, ale nie będzie to możliwe, dopóki nie zostanie otwarte w formacie GUI. Masz pomysł, jak mogę to obejść?
Arkya Chatterjee
2
Powinno być dość oczywiste, że będzie to działać tylko na kontenerze, na którym zainstalowano bash.
Inżynier oprogramowania
2
Dla każdego, kto zastanawia się, jak to zrobić w Windows Container / Powershell, polecenie to docker exec -ti <name> powershell( źródło )
sprzedaj
1
@ sprzedał mój kontener / obraz z jakiegoś powodu nie miał PowerShell, więc docker exec -ti <name> cmddziałał. W przypadku innych początkujących, takich jak ja, pamiętaj o użyciu nazwy instancji kontenera z docker ps(coś takiego jak 070494393ca5) zamiast czytelnej nazwy, którą jej przypisałeś.
Simon_Weaver
1
dotyczące PowerShell w obrazach github.com/aspnet/aspnet-docker/issues/362 - a jeśli potrzebujesz tylko curl na obrazach systemu Windows: blogs.technet.microsoft.com/virtualization/2017/12/19/…
Simon_Weaver
162

W przypadku zatrzymania kontenera lub braku powłoki (np. hello-worldWspomnianej w instrukcji instalacji lub nie alpine traefik), jest to prawdopodobnie jedyna możliwa metoda eksploracji systemu plików.

Możesz zarchiwizować system plików swojego kontenera w pliku tar:

docker export adoring_kowalevski > contents.tar

Lub wylistuj pliki:

docker export adoring_kowalevski | tar t

Pamiętaj, że w zależności od obrazu może to zająć trochę czasu i miejsca na dysku.

Ilya Murav'jov
źródło
12
Chciałem po prostu wyświetlić zawartość kontenera, w którym nie ma zainstalowanych standardowych narzędzi UNIX. Odmiana exportpowyższego przykładu trafiła w dziesiątkę:docker export adoring_kowalevski | tar tf -
berto
3
Ostrzeżenie dla nieostrożnych: może to spowodować eksport dużej ilości danych (> GB) i zająć dużo czasu.
Vince Bowdren,
5
@berto nie oznacza, że ​​jest to ogromna sprawa, ale f -na końcu polecenia nie powinieneś potrzebować , tar domyślnie czyta ze standardowego wejścia. Po prostu docker export adoring_kowalevski | tar tdziała.
Shaun Bouckaert,
Im prościej, tym lepiej; super, dzięki za wskazówkę! 🙌🏽
berto
1
@ShaunBouckaert, domyślna wartość tar fzależy od konfiguracji użytkownika. Jedna część to TAPEzmienna środowiskowa. Inne są kontrolowane w ramach kompilacji. Efektem netto jest to, że nigdy nie należy zakładać, że czyta stdin lub pisze stdout, ale zawsze podaje to wprost.
roaima
42

System plików kontenera znajduje się w folderze danych dokera, zwykle w / var / lib / docker. Aby uruchomić i sprawdzić działający system plików kontenerów, wykonaj następujące czynności:

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

A teraz bieżący katalog roboczy jest katalogiem głównym kontenera.

Rovanion
źródło
3
nie obejmie to jednak żadnych zamontowanych woluminów.
hwjp
34

Przed utworzeniem kontenera:

Jeśli chcesz zbadać strukturę obrazu zamontowanego wewnątrz kontenera, możesz to zrobić

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

Zapewniłoby to widoczność wszystkich warstw obrazu i jego konfiguracji, która jest obecna w plikach json.

Po utworzeniu kontenera:

Do tego jest już wiele odpowiedzi powyżej. mój preferowany sposób to:

docker exec -t -i container /bin/bash
Gaurav24
źródło
Zobacz też sreeninet.wordpress.com/2016/06/11/… .
Jaime Hablutzel
Należy tutaj wspomnieć, że uruchamianie bash wewnątrz kontenera działa tylko wtedy, gdy robisz to na maszynie o tej samej architekturze co obraz. Jeśli używasz komputera PC, aby zajrzeć do systemu plików graficznych raspberry pi, sztuczka bash nie zadziała.
Maxim Kulkin
@MaximKulkin Naprawdę? Jeśli kontenerem jest Linux, nie ma znaczenia, jaki jest host, jeśli dostępna jest wersja bash. Być może myślisz o kontenerach Windows?
Thorbjørn Ravn Andersen
26

Najbardziej pozytywna odpowiedź działa dla mnie, kiedy kontener jest faktycznie uruchomiony, ale kiedy nie można uruchomić i na przykład chcesz skopiować pliki z kontenera, to wcześniej mnie to zapisało:

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

Dzięki dockerowi cp ( link ) możesz kopiować bezpośrednio z kontenera, ponieważ był to jakikolwiek inny element twojego systemu plików. Na przykład odzyskiwanie wszystkich plików w kontenerze:

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

Pamiętaj, że nie musisz określać, że chcesz kopiować rekurencyjnie.

Julius Printz
źródło
6
dlaczego to nie ma więcej + 1! zdecydowanie najlepszy sposób
Nicholas DiPiazza
Jest to nawet prostsze niż eksportowanie za pomocą tar. Musiałem użyć opcji -L, aby dostać się do plików za pośrednictwem dowiązań symbolicznych. Nie musisz uruchamiać kontenera!
MKaama,
17

Na Ubuntu 14.04 z systemem Docker 1.3.1 znalazłem główny system plików kontenera na hoście w następującym katalogu:

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

Pełna informacja o wersji Docker:

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
piercebot
źródło
Działa jak urok: name = <nazwa> dockerId = $ (doker inspect -f {{.Id}} $ name) / var / lib / docker / devicemapper / mnt / $ dockerId / rootfs /
Florent
3
Z Ubuntu 16.10 i dokerem 1.12.1 już tak nie jest (brak devicemapperkatalogu). Plik istnieje pod /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/.... Nie jestem pewien, jak przenośny / bezpieczny jest dostęp do plików
WoJ,
1
Począwszy od 1.10, Docker wprowadził nowy model pamięci adresowalnej pod kątem zawartości, który nie używa losowo generowanego identyfikatora UUID, jak wcześniej zarówno dla identyfikatorów warstw, jak i kontenerów. W nowym modelu jest to zastąpione bezpiecznym hashem treści dla id warstwy. Ta metoda nie będzie już działać.
Artem Dolobanko,
To nie jest przenośne i zależy w dużej mierze od wyboru sterownika pamięci . Nie jestem pewien, czy na przykład rozwiązanie będzie działać direct-lvm.
rustyx
14

Spróbuj użyć

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

Może istnieć możliwość, że bash nie zostanie zaimplementowany. do tego możesz użyć

docker exec -it <container-name> sh
Gaurav Sharma
źródło
12

Używam innej brudnej sztuczki, która jest agnostyczna aufs / devicemapper.

Patrzę na polecenie, które uruchamia kontener np. docker ps I jeśli jest to apache lub javapo prostu wykonuję następujące czynności:

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

i voilá jesteś w pojemniku.

Zasadniczo możesz jako główny dysk CD w /proc/<PID>/root/folderze, o ile proces ten jest uruchamiany przez kontener. Uważaj dowiązania symboliczne nie będą miały sensu podczas korzystania z tego trybu.

telamon
źródło
Dodatkowe informacje na temat tej metody tutaj: superuser.com/a/1288058/195840
Eduardo Lucio
12

Najczęściej głosowana odpowiedź jest dobra, chyba że twój kontener nie jest rzeczywistym systemem Linux.

Wiele kontenerów (szczególnie tych opartych na go) nie ma żadnych standardowych plików binarnych (nie /bin/bashlub /bin/sh). W takim przypadku musisz uzyskać bezpośredni dostęp do rzeczywistego pliku kontenerów:

Działa jak marzenie:

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

Uwaga: musisz uruchomić go jako root.

Florent
źródło
To już nie działa. Folder devicemapper nie istnieje.
0xcaff
Byłoby miło, gdyby ludzie z nieaktualnymi odpowiedziami je posprzątali
Matthew Purdon
2
Zaktualizowałem polecenie, aby pasowało do nowej struktury magazynu dokerów.
Florent,
10

W moim przypadku żadna powłoka nie była obsługiwana w kontenerze, z wyjątkiem sh. To zadziałało jak urok

docker exec -it <container-name> sh
shx
źródło
10

możesz użyć nurkowania do interaktywnego przeglądania zawartości obrazu za pomocą TUI

https://github.com/wagoodman/dive

wprowadź opis zdjęcia tutaj

Andy Wong
źródło
Nurkowanie jest naprawdę idealnym narzędziem!
Laurent
5

Spowoduje to uruchomienie sesji bash dla obrazu:

Uruchom okno dokowane --rm -it --entrypoint = / bin / bash

LeYAUable
źródło
1
jest to przydatne, gdy domyślny punkt wejścia nie działa
przeanalizuj
4

Dla mnie ten działa dobrze (dzięki ostatnim komentarzom do wskazania katalogu / var / lib / docker / ):

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

Tutaj 2465790aa2c4 jest krótki identyfikator systemem pojemnika (jak wyświetlane przez Döcker ps ), a następnie przez gwiazdę.

dashohoxha
źródło
4

W nowszych wersjach Dockera możesz uruchomić, docker exec [container_name]który uruchamia powłokę w twoim kontenerze

Aby uzyskać listę wszystkich plików w kontenerze, po prostu uruchom docker exec [container_name] ls

xrh
źródło
1
Próbowałem tego i nie zadziałało. Powyższa sugestia Khalila Gharbaoui zadziałała.
Nick
To działało dla mnie. Możesz także wypróbować identyfikator kontenera zamiast nazwy obrazu
Diwann
4

W przypadku sterownika dokującego aufs:

Skrypt znajdzie katalog główny kontenera (Test w oknie dokowanym 1.7.1 i 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
qxo
źródło
4

Żadna z istniejących odpowiedzi nie dotyczy przypadku kontenera, który opuścił (i nie można go zrestartować) i / lub nie ma zainstalowanej powłoki (np. Bez destylacji). Ten działa tak długo, jak masz dostęp root do hosta Docker.

W celu prawdziwej ręcznej kontroli najpierw sprawdź identyfikatory warstw:

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

Na wyjściu powinieneś zobaczyć coś takiego

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

Przejdź do tego folderu (jako root), aby znaleźć bieżący widoczny stan systemu plików kontenera.

Raphael
źródło
3

Ta odpowiedź pomoże tym (jak ja), którzy chcą eksplorować system plików woluminu dokującego, nawet jeśli kontener nie jest uruchomiony.

Lista uruchomionych kontenerów dokowanych:

docker ps

=> ID POJEMNIKA „4c721f1985bd”

Spójrz na punkty montowania woluminu dokera na lokalnym komputerze fizycznym ( https://docs.docker.com/engine/tutorials/dockervolumes/ ):

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

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

Mówi mi to, że lokalny fizyczny katalog maszynowy / tmp / container-garren jest odwzorowany na miejsce docelowe woluminu dokowanego / tmp.

Znajomość lokalnego katalogu fizycznej maszyny (/ tmp / container-garren) oznacza, że ​​mogę badać system plików, niezależnie od tego, czy jest uruchomiony kontener dokera. Było to bardzo ważne, aby pomóc mi zorientować się, że istnieją pewne dane resztkowe, które nie powinny były zostać utrwalone nawet po wyłączeniu kontenera.

Garren S.
źródło
1
Znajduje tylko katalog lokalny, który jest podłączony jako wolumin wewnątrz kontenera, ale nie pozwala na dostęp do całego systemu plików kontenera.
Bojan Komazec
3

inną sztuczką jest użycie narzędzia atomowego do zrobienia czegoś takiego:

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

Obraz Dockera zostanie zamontowany w / path / to / mnt, abyś mógł go obejrzeć.

Giuseppe Scrivano
źródło
Ale żeby to działało, musisz mieć specjalnie wykonane pojemniki, prawda? Może powinieneś dodać to jako zastrzeżenie, ponieważ większość ludzi nie będzie w stanie sprzedać go zespołowi / firmie jako rozwiązanie ...
Angelos Pikoulas,
3

Tylko dla LINUX

Najprostszym sposobem, którego używam, było użycie proc dir, czyli kontenera, który musi być uruchomiony, aby sprawdzić pliki kontenera dokera.

  1. Znajdź identyfikator procesu (PID) kontenera i zapisz w jakiejś zmiennej

    PID = $ (doker sprawdza -f '{{.State.Pid}}' twoja-nazwa-kontenera-tutaj)

  2. Upewnij się, że proces kontenerowy jest uruchomiony, i użyj zmiennej nameto, aby dostać się do folderu kontenera

    cd / proc / $ PID / root

Jeśli chcesz przejść przez katalog bez znajdowania numeru PID, używając tylko tego długiego polecenia

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

Wskazówki:

Po wejściu do kontenera wszystko, co zrobisz, wpłynie na faktyczny proces kontenera, takie jak zatrzymanie usługi lub zmiana numeru portu.

Mam nadzieję, że to pomoże

Uwaga:

Ta metoda działa tylko wtedy, gdy kontener nadal działa, w przeciwnym razie katalog nie istniałby, gdyby kontener został zatrzymany lub usunięty

Aditya Kresna Permana
źródło
2

Mój preferowany sposób, aby zrozumieć, co dzieje się w pojemniku, to:

  1. odsłonić -p 8000

    docker run -it -p 8000:8000 image
    
  2. Uruchom serwer w nim

    python -m SimpleHTTPServer
    
kgnete
źródło
2

W przypadku już działającego kontenera możesz wykonać:

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

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

Musisz być rootem, aby cd do tego katalogu. Jeśli nie jesteś rootem, spróbuj „sudo su” przed uruchomieniem polecenia.

Edycja: Po wersji 1.3 zobacz odpowiedź Jiriego - lepiej.

AlonL
źródło
4
Jestem zdecydowanie stronniczy od „sudo -i” zamiast „sudo su”, ponieważ nie ma powodu, aby uruchamiać program suid, który uruchamia inny program suid, który uruchamia powłokę. Wytnij środkowego człowieka. :)
dannysauer
Twoja odpowiedź jest bardzo dobra, tylko ścieżka nie jest. Powinieneś użyć ścieżki piercebota.
Florent,
2

Jeśli korzystasz z Docker v19.03, wykonaj poniższe czynności.

# 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
saurabh tiwari
źródło
1

Jeśli używasz sterownika magazynu AUFS, możesz użyć mojego skryptu warstwy dokowania, aby znaleźć katalog główny systemu plików dowolnego kontenera (mnt) i warstwę zapisu do zapisu:

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

Edytuj 2018-03-28:
Warstwa dokera została zastąpiona przez kopię zapasową dokera

Vince
źródło
1

docker execPolecenie uruchomienia polecenia uruchomionego w pojemniku może pomóc w wielu przypadkach.

Użycie: docker exec [OPCJE] CONTAINER COMMAND [ARG ...]

Uruchom polecenie w działającym kontenerze

Opcje:
  -d, --detach Tryb odłączony: uruchom polecenie w tle
      --detach-keys string Zastąp sekwencję klawiszy do odłączania a
                             pojemnik
  -e, --env list Ustaw zmienne środowiskowe
  -i, --interactive Pozostaw STDIN otwarty, nawet jeśli nie jest dołączony
      --privileged Daje rozszerzone uprawnienia do polecenia
  -t, --tty Przydziel pseudo-TTY
  -u, --user string Nazwa użytkownika lub UID (format:
                             [:])
  -w, --workdir string Katalog roboczy wewnątrz kontenera

Na przykład :

1) Dostęp bash do działającego systemu plików kontenera:

docker exec -it containerId bash 

2) Dostęp bash do działającego systemu plików kontenera jako root, aby mieć wymagane uprawnienia:

docker exec -it -u root containerId bash  

Jest to szczególnie przydatne, aby móc wykonać pewne przetwarzanie jako root w kontenerze.

3) Dostęp bash do działającego systemu plików kontenera z określonym katalogiem roboczym:

docker exec -it -w /var/lib containerId bash 
davidxxx
źródło
0

Możesz uruchomić bash wewnątrz kontenera za pomocą: $ docker run -it ubuntu /bin/bash

Yang Yu
źródło