Erkunden des Dateisystems des Docker-Containers


650

Ich habe bei Docker festgestellt, dass ich verstehen muss, was in einem Container passiert oder welche Dateien dort vorhanden sind. Ein Beispiel ist das Herunterladen von Bildern aus dem Docker-Index. Sie haben keine Ahnung, was das Bild enthält, sodass die Anwendung nicht gestartet werden kann.

Was ideal wäre, wäre in der Lage zu sein, in sie oder gleichwertig zu ssh. Gibt es ein Werkzeug, um dies zu tun, oder ist meine Konzeptualisierung von Docker falsch, wenn ich denke, dass ich dazu in der Lage sein sollte?


13
In den neuesten Versionen von Docker ist Folgendes möglich : docker exec <container> bash. Sie öffnen also einfach eine Hülle im Behälter.
Dashohoxha

7
Das Ausführen von Bash auf einem Container funktioniert nur, wenn Bash im Container installiert ist
Christopher Thomas

7
Ebenso können Sie: docker exec <container> ls <dir path>und docker exec <container> cat <file path>. Für Bash fügen Sie jedoch die -itOptionen hinzu.
Noam Manos


3
@ ChristopherThomas, genau. Aus diesem Grund habe ich festgestellt, dass der einzige robuste Weg, dies zu tun docker image save image_name > image.tar, der in der Antwort von @ Gaurav24 angegebene ist.
Jaime Hablutzel

Antworten:


735

UPDATE
Einfachste Methode: Verwenden von Docker Exec

Docker Version 1.3 oder neuer unterstützt den Befehl exec, der sich ähnlich verhält nsenter. Dieser Befehl kann einen neuen Prozess in einem bereits ausgeführten Container ausführen (in einem Container muss der PID 1-Prozess bereits ausgeführt werden). Sie können ausführen /bin/bash, um den Containerstatus zu untersuchen:

docker exec -t -i mycontainer /bin/bash

Siehe Dokumentation zur Docker-Befehlszeile

Alternative Methode 1
Schnappschuss

Sie können das Container-Dateisystem folgendermaßen auswerten:

# 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

Auf diese Weise können Sie das Dateisystem des laufenden Containers genau zum richtigen Zeitpunkt auswerten. Der Container läuft noch, zukünftige Änderungen sind nicht enthalten.

Sie können den Snapshot später löschen mit (Dateisystem des laufenden Containers ist nicht betroffen!):

docker rmi mysnapshot

Alternative Methode 2
ssh

Wenn Sie einen kontinuierlichen Zugriff benötigen, können Sie sshd in Ihrem Container installieren und den sshd-Daemon ausführen:

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

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

Auf diese Weise können Sie Ihre App mit ssh ausführen (verbinden und ausführen, was Sie möchten).

UPDATE: Alternative Methode 3
nsenter

Verwendung nsenterfinden Sie unter https://web.archive.org/web/20160305150559/http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/

Die Kurzversion lautet: Mit nsenter können Sie eine Shell in einen vorhandenen Container einfügen, auch wenn in diesem Container weder SSH noch ein spezieller Daemon ausgeführt wird


6
Beachten Sie jedoch, dass Sie den Befehl "docker cp" verwenden müssen, wenn Sie Zugriff auf Dateien benötigen. Verwendung: docker cp CONTAINER: PATH HOSTPATH ​​Kopieren Sie Dateien / Ordner aus dem Container-Dateisystem in den Host-Pfad. Pfade sind relativ zum Stammverzeichnis des Dateisystems. #> Docker cp 7bb0e258aefe: / etc / debian_version. #> Docker cp blue_frog: / etc / hosts.
Amos Folarin

4
Option 4 ist so wichtig, dass sie nach oben verschoben und umbenannt werden sollte Option 1.
automorph

5
@ JanusTroelsen Wenn es keine Shell gibt, können Sie sie installieren - zum Beispiel in Dockerfile für alpines Linux (das tatsächlich keine Shell hat) von: RUN apk update && apk add bash(Größe: ~ 4 MB)
Kamil Kiełczewski

2
Nach meiner eigenen Erfahrung besteht die Einschränkung bei Docker exec darin, dass der Befehl auf einem laufenden Container oder als eine Art Einstiegspunkt hinzugefügt werden muss. Daher liegt ein angehaltener Container außerhalb des Anwendungsbereichs dieser Methode.
Webwoman

1
Um die Linux-Shell von Window zu verwenden, verwenden Siedocker exec -t -i mycontainer /bin/sh
Jason Masters

266

UPDATE: ENTDECKEN!

Mit diesem Befehl sollten Sie einen laufenden Docker-Container untersuchen können :

docker exec -it name-of-container bash

Das Äquivalent dazu in Docker-Compose wäre:

docker-compose exec web bash

(Web ist in diesem Fall der Name des Dienstes und hat standardmäßig tty.)

Sobald Sie drinnen sind, tun Sie:

ls -lsa

oder ein anderer Bash-Befehl wie:

cd ..

Mit diesem Befehl sollten Sie ein Docker-Image untersuchen :

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

Einmal drinnen:

ls -lsa

oder ein anderer Bash-Befehl wie:

cd ..

Das -itsteht für interaktiv ... und tty.


Mit diesem Befehl können Sie einen laufenden Docker-Container oder ein laufendes Image überprüfen :

docker inspect name-of-container-or-image

Vielleicht möchten Sie dies tun und herausfinden, ob es welche gibt bashoder shdarin. Suchen Sie in der json-Rückgabe nach Entrypoint oder cmd.

Siehe Docker Exec-Dokumentation

Siehe Docker-Compose Exec-Dokumentation

Siehe Docker-Inspektionsdokumentation


1
Das ist sehr nützlich, danke! Ich muss eine Datei, die in einer Docker-Image-Dateistruktur enthalten ist, per Drag & Drop in eine Anwendung ziehen, aber das ist nur möglich, wenn sie in einem GUI-Format geöffnet wird. Irgendeine Idee, wie ich das umgehen könnte?
Arkya Chatterjee

2
Es sollte ziemlich offensichtlich sein, dass dies nur auf einem Container funktioniert, auf dem bash installiert ist.
Software Engineer

2
Für alle, die sich docker exec -ti <name> powershell
ansehen,

1
@ssell mein Container / Bild hatte aus irgendeinem Grund keine Powershell, also hat es docker exec -ti <name> cmdfunktioniert. Und für andere Neulinge wie mich stellen Sie sicher, dass Sie den Namen der Containerinstanz von docker ps(so etwas wie 070494393ca5) anstelle des lesbaren Namens verwenden, den Sie ihm zugewiesen haben.
Simon_Weaver

1
in Bezug auf Powershell in Bildern github.com/aspnet/aspnet-docker/issues/362 - und wenn Sie nur Locken auf Windows-Bildern benötigen: blogs.technet.microsoft.com/virtualization/2017/12/19/…
Simon_Weaver

162

Falls Ihr Container gestoppt ist oder keine Shell hat (z. B. hello-worldim Installationshandbuch erwähnt oder nicht alpine traefik), ist dies wahrscheinlich die einzig mögliche Methode, um das Dateisystem zu erkunden.

Sie können das Dateisystem Ihres Containers in einer TAR-Datei archivieren:

docker export adoring_kowalevski > contents.tar

Oder listen Sie die Dateien auf:

docker export adoring_kowalevski | tar t

Beachten Sie, dass es je nach Image einige Zeit und Speicherplatz dauern kann.


12
Ich wollte einfach den Inhalt eines Containers auflisten, auf dem keine Standard-UNIX-Tools installiert sind. Eine Variation des exportobigen Beispiels traf den Punkt:docker export adoring_kowalevski | tar tf -
Berto

3
Eine Warnung an Unachtsame: Dies kann viele Daten (> GB) exportieren und lange dauern.
Vince Bowdren

5
@berto nicht, dass es eine massive Sache ist, aber Sie sollten nicht f -am Ende Ihres Befehls benötigen , tar liest standardmäßig von der Standardeingabe. Funktioniert einfach docker export adoring_kowalevski | tar t.
Shaun Bouckaert

Je einfacher desto besser; super, danke für den tipp! 🙌🏽
Berto

1
@ShaunBouckaert Der Standardwert für tar fhängt von der Konfiguration ab. Ein Teil ist die TAPEUmgebungsvariable. Andere werden als Teil des Builds gesteuert. Der Nettoeffekt ist, dass man niemals annehmen sollte, dass es stdin liest oder stdout schreibt, sondern es immer explizit angibt.
Roaima

42

Das Dateisystem des Containers befindet sich im Datenordner von Docker, normalerweise in / var / lib / docker. Gehen Sie wie folgt vor, um ein laufendes Container-Dateisystem zu starten und zu überprüfen:

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

Und jetzt ist das aktuelle Arbeitsverzeichnis das Stammverzeichnis des Containers.


3
Dies schließt jedoch keine gemounteten Volumes ein.
Hwjp

34

Vor der Containererstellung:

Wenn Sie die Struktur des Bilds untersuchen möchten, das im Container montiert ist, können Sie dies tun

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

Dies gibt Ihnen die Sichtbarkeit aller Ebenen eines Bildes und seiner Konfiguration, die in JSON-Dateien vorhanden sind.

Nach der Containererstellung:

Dafür gibt es oben schon viele Antworten. Mein bevorzugter Weg, dies zu tun, wäre -

docker exec -t -i container /bin/bash


Es sollte hier erwähnt werden, dass das Ausführen von Bash im Container nur funktioniert, wenn Sie es auf einem Computer mit derselben Architektur wie das Image ausführen. Wenn Sie auf dem PC versuchen, einen Blick in das Image-Dateisystem von Himbeer-Pi zu werfen, funktioniert der Bash-Trick nicht.
Maxim Kulkin

@ MaximKulkin Wirklich? Wenn der Container Linux ist, spielt es keine Rolle, was der Host ist, wenn Bash verfügbar ist. Vielleicht denken Sie an Windows-Container?
Thorbjørn Ravn Andersen

25

Die am besten bewertete Antwort funktioniert für mich, wenn der Container tatsächlich gestartet wird, aber wenn er nicht ausgeführt werden kann und Sie beispielsweise Dateien aus dem Container kopieren möchten, hat mich dies zuvor gespeichert:

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

Dank Docker CP ( Link ) können Sie direkt aus dem Container kopieren, wie es jeder andere Teil Ihres Dateisystems war. Beispiel: Wiederherstellen aller Dateien in einem Container:

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

Beachten Sie, dass Sie nicht angeben müssen, dass Sie rekursiv kopieren möchten.


6
warum hat das nicht mehr +1! definitiv der beste Weg
Nicholas DiPiazza

Dies ist noch einfacher als der Export über Teer. Ich musste -L verwenden, um über Symlinks zu den Dateien zu gelangen. Der Container muss nicht ausgeführt werden!
MKaama

17

Unter Ubuntu 14.04 unter Docker 1.3.1 fand ich das Container-Root-Dateisystem auf dem Host-Computer im folgenden Verzeichnis:

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

Vollständige Informationen zur Docker-Version:

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

Funktioniert wie ein Zauber: name = <name> dockerId = $ (docker inspect -f {{.Id}} $ name) / var / lib / docker / devicemapper / mnt / $ dockerId / rootfs /
Florent

3
Mit Ubuntu 16.10 und Docker 1.12.1 ist dies leider nicht mehr der Fall (kein devicemapperVerzeichnis). Die Datei existiert unter /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/.... Ich bin nicht sicher, wie portabel / sicher es ist, dort auf Dateien zuzugreifen
WoJ

1
Ab 1.10 führte Docker ein neues inhaltsadressierbares Speichermodell ein, das keine zufällig generierte UUID verwendet, wie dies zuvor sowohl für Layer- als auch für Container-IDs der Fall war. Im neuen Modell wird dies durch einen sicheren Inhalts-Hash für die Layer-ID ersetzt. Diese Methode funktioniert also nicht mehr.
Artem Dolobanko

Dies ist nicht portabel und hängt stark von der Wahl des Speichertreibers ab . Ich bin mir nicht sicher, ob die Lösung direct-lvmzum Beispiel funktioniert .
Rustyx

14

Versuchen Sie es mit

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

Möglicherweise wird Bash nicht implementiert. dafür kannst du verwenden

docker exec -it <container-name> sh

12

Ich benutze einen anderen schmutzigen Trick, der aufs / devicemapper agnostisch ist.

Ich schaue auf den Befehl, dass der Container läuft, zB docker ps und wenn es ein Apache ist oder javaich mache einfach folgendes:

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

und voilá du bist im Container.

Grundsätzlich können Sie als Root-CD in einen /proc/<PID>/root/Ordner, solange dieser Prozess vom Container ausgeführt wird. Beachten Sie, dass Symlinks in diesem Modus keinen Sinn ergeben.


Zusätzliche Informationen zu dieser Methode hier: superuser.com/a/1288058/195840
Eduardo Lucio

12

Die am häufigsten gewählte Antwort ist gut, es sei denn, Ihr Container ist kein tatsächliches Linux-System.

Viele Container (insbesondere die Go-basierten) haben keine Standard-Binärdatei (no /bin/bashor /bin/sh). In diesem Fall müssen Sie direkt auf die eigentliche Containerdatei zugreifen:

Klappt wunderbar:

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

Hinweis: Sie müssen es als root ausführen.


Das funktioniert nicht mehr. Der Devicemapper-Ordner ist nicht vorhanden.
0xcaff

Es wäre schön, wenn Leute mit veralteten Antworten sie aufräumen würden
Matthew Purdon

2
Ich habe den Befehl aktualisiert, um ihn an die neue Docker-Speicherstruktur anzupassen.
Florent

10

In meinem Fall wurde außer im Shell keine Shell unterstützt sh. Das hat also wie ein Zauber gewirkt

docker exec -it <container-name> sh


5

Dadurch wird eine Bash-Sitzung für das Bild gestartet:

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


1
Dies ist nützlich, wenn der Standardeinstiegspunkt nicht ausgeführt wird
analysiert diesen

4

Für mich funktioniert dieses gut (dank der letzten Kommentare für den Hinweis auf das Verzeichnis / var / lib / docker / ):

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

Hier ist 2465790aa2c4 die kurze ID des laufenden Containers (wie von Docker ps angezeigt ), gefolgt von einem Stern.


4

In neueren Versionen von Docker können Sie ausführen, docker exec [container_name]wobei eine Shell in Ihrem Container ausgeführt wird

Um eine Liste aller Dateien in einem Container zu erhalten, führen Sie sie einfach aus docker exec [container_name] ls


1
Ich habe es versucht und es hat nicht funktioniert. Der obige Vorschlag von Khalil Gharbaoui hat funktioniert.
Nick

Das hat bei mir funktioniert. Sie können es auch mit der Container-ID anstelle des
Bildnamens

4

Für Docker aufs Treiber:

Das Skript findet das Container-Stammverzeichnis (Test auf Docker 1.7.1 und 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

Keine der vorhandenen Antworten bezieht sich auf den Fall eines Containers, der beendet wurde (und nicht neu gestartet werden kann) und / oder auf dem keine Shell installiert ist (z. B. notleidende). Dieser funktioniert, solange Sie Root-Zugriff auf den Docker-Host haben.

Ermitteln Sie für eine echte manuelle Überprüfung zuerst die Layer-IDs:

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

In der Ausgabe sollten Sie so etwas sehen

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

Navigieren Sie in diesen Ordner (als Root), um den aktuell sichtbaren Status des Container-Dateisystems zu ermitteln.


3

Diese Antwort hilft denjenigen (wie mir), die das Docker-Volume-Dateisystem erkunden möchten, auch wenn der Container nicht ausgeführt wird.

Liste laufender Docker-Container:

docker ps

=> CONTAINER ID "4c721f1985bd"

Sehen Sie sich die Docker-Volume-Mount-Punkte auf Ihrem lokalen physischen Computer an ( https://docs.docker.com/engine/tutorials/dockervolumes/ ):

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

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

Dies sagt mir, dass das lokale physische Maschinenverzeichnis / tmp / container-garren dem Docker-Volume-Ziel / tmp zugeordnet ist.

Wenn ich das lokale Verzeichnis der physischen Maschine (/ tmp / container-garren) kenne, kann ich das Dateisystem untersuchen, ob der Docker-Container ausgeführt wird oder nicht. Dies war entscheidend, um herauszufinden, dass es einige Restdaten gab, die auch nach dem Ausführen des Containers nicht hätten bestehen dürfen.


1
Dadurch wird nur ein lokales Verzeichnis gefunden, das als Volume im Container bereitgestellt ist, jedoch nicht den Zugriff auf das gesamte Dateisystem des Containers ermöglicht.
Bojan Komazec

3

Ein weiterer Trick besteht darin, das Atom- Tool zu verwenden, um Folgendes zu tun:

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

Das Docker-Image wird an / path / to / mnt gemountet, damit Sie es überprüfen können.


Aber Sie müssen speziell angefertigte Behälter haben, damit dies funktioniert, oder? Vielleicht sollten Sie es als Einschränkung hinzufügen, weil die meisten Leute es nicht als Lösung an ihr Team / Unternehmen verkaufen können ...
Angelos Pikoulas

3

Nur für LINUX

Der einfachste Weg, den ich benutze, war die Verwendung von proc dir, dh dem Container, der ausgeführt werden muss, um die Docker-Container-Dateien zu überprüfen.

  1. Ermitteln Sie die Prozess-ID (PID) des Containers und speichern Sie sie in einer Variablen

    PID = $ (Docker inspizieren -f '{{.State.Pid}}' Ihren-Containernamen-hier)

  2. Stellen Sie sicher, dass der Containerprozess ausgeführt wird, und verwenden Sie den Variablennamen, um in den Containerordner zu gelangen

    cd / proc / $ PID / root

Wenn Sie mit diesem langen Befehl durch das Verzeichnis gelangen möchten, ohne die PID-Nummer herauszufinden

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

Tipps:

Nachdem Sie den Container betreten haben, wirkt sich alles, was Sie tun, auf den tatsächlichen Prozess des Containers aus, z. B. das Beenden des Dienstes oder das Ändern der Portnummer.

Ich hoffe es hilft

Hinweis:

Diese Methode funktioniert nur, wenn der Container noch ausgeführt wird. Andernfalls würde das Verzeichnis nicht mehr existieren, wenn der Container gestoppt oder entfernt wurde


2

Mein bevorzugter Weg, um zu verstehen, was im Container vor sich geht, ist:

  1. -p 8000 aussetzen

    docker run -it -p 8000:8000 image
    
  2. Starten Sie den Server darin

    python -m SimpleHTTPServer
    

2

Für einen bereits laufenden Container können Sie Folgendes tun:

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

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

Sie müssen root sein, um in dieses Verzeichnis zu cd. Wenn Sie nicht root sind, versuchen Sie 'sudo su', bevor Sie den Befehl ausführen.

Bearbeiten: Nach v1.3 sehen Sie Jiris Antwort - es ist besser.


4
Ich bin eher an "sudo -i" als an "sudo su" interessiert, weil es wenig Grund gibt, ein suid-Programm auszuführen, das ein anderes suid-Programm startet, das eine Shell startet. Schneiden Sie den mittleren Mann aus. :)
dannysauer

Ihre Antwort ist sehr gut, nur der Weg ist nicht. Sie sollten den Piercebot-Pfad verwenden.
Florent

2

Wenn Sie Docker v19.03 verwenden, führen Sie die folgenden Schritte aus.

# 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

Wenn Sie den AUFS-Speichertreiber verwenden, können Sie mein Docker-Layer- Skript verwenden, um den Dateisystemstamm (mnt) und die Readwrite -Ebene eines Containers zu finden:

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

Edit 2018-03-28:
Docker-Layer wurde durch Docker-Backup ersetzt


1

Der docker execBefehl zum Ausführen eines Befehls in einem laufenden Container kann in mehreren Fällen hilfreich sein.

Verwendung: docker exec [OPTIONEN] CONTAINER-BEFEHL [ARG ...]

Führen Sie einen Befehl in einem laufenden Container aus

Optionen:
  -d, --detach Freistehender Modus: Befehl im Hintergrund ausführen
      --detach-keys string Überschreibt die Tastenfolge zum Trennen von a
                             Container
  -e, --env list Umgebungsvariablen festlegen
  -i, --interactive Halten Sie STDIN offen, auch wenn es nicht angeschlossen ist
      --privileged Geben Sie dem Befehl erweiterte Berechtigungen
  -t, --tty Ordne ein Pseudo-TTY zu
  -u, --user string Benutzername oder UID (Format:
                             [:])
  -w, --workdir string Arbeitsverzeichnis im Container

Beispielsweise :

1) Zugriff in Bash auf das laufende Container-Dateisystem:

docker exec -it containerId bash 

2) Zugriff in Bash auf das laufende Container-Dateisystem als Root, um die erforderlichen Rechte haben zu können:

docker exec -it -u root containerId bash  

Dies ist besonders nützlich, um eine Verarbeitung als Root in einem Container durchführen zu können.

3) Zugriff in Bash auf das laufende Container-Dateisystem mit einem bestimmten Arbeitsverzeichnis:

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

0

Sie können eine Bash im Container ausführen, indem Sie Folgendes ausführen: $ docker run -it ubuntu /bin/bash

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.