Esplorazione del file system del container Docker


652

Ho notato con la finestra mobile che ho bisogno di capire cosa sta succedendo all'interno di un contenitore o quali file esistono. Un esempio è il download di immagini dall'indice docker: non hai idea di cosa contenga l'immagine, quindi è impossibile avviare l'applicazione.

Ciò che sarebbe l'ideale è essere in grado di inserirli o equivalere. C'è uno strumento per farlo, o la mia concettualizzazione della finestra mobile è errata nel pensare che dovrei essere in grado di farlo.


13
Nelle ultime versioni di Docker, qualcosa di simile a questo è possibile: docker exec <container> bash. Quindi, basta aprire una shell all'interno del contenitore.
dashohoxha,

7
l'esecuzione di bash su un container funziona solo se bash è installato all'interno del container
Christopher Thomas,

7
Allo stesso modo, puoi fare: docker exec <container> ls <dir path>e docker exec <container> cat <file path>. Per bash, tuttavia, aggiungi le -itopzioni.
Noam Manos,


3
@ChristopherThomas, esattamente. Per questo docker image save image_name > image.tarmotivo ho scoperto che l'unico modo affidabile per farlo è quello indicato nella risposta di @ Gaurav24.
Jaime Hablutzel,

Risposte:


737

AGGIORNAMENTO
Metodo più semplice: utilizzo della finestra mobile exec

Docker versione 1.3 o successiva supporta il comando execche si comporta in modo simile nsenter. Questo comando può eseguire un nuovo processo in un contenitore già in esecuzione (nel contenitore deve essere già in esecuzione un processo PID 1). È possibile eseguire /bin/bashper esplorare lo stato del contenitore:

docker exec -t -i mycontainer /bin/bash

consultare la documentazione della riga di comando Docker

Metodo alternativo 1
Istantanea

È possibile valutare il filesystem contenitore in questo modo:

# 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

In questo modo, è possibile valutare il filesystem del container in esecuzione nel preciso momento temporale. Il contenitore è ancora in esecuzione, non sono incluse modifiche future.

Successivamente puoi eliminare l'istantanea usando (il filesystem del container in esecuzione non è interessato!):

docker rmi mysnapshot

Metodo alternativo 2
ssh

Se hai bisogno di un accesso continuo, puoi installare sshd nel tuo contenitore ed eseguire il demone sshd:

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

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

In questo modo, puoi eseguire la tua app usando ssh (connettiti ed esegui ciò che desideri).

AGGIORNAMENTO: metodo alternativo 3
nsenter

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

La versione breve è: con nsenter, è possibile ottenere una shell in un contenitore esistente, anche se quel contenitore non esegue SSH o alcun tipo di demone per scopi speciali


6
ma nota se hai bisogno di accedere ai file usa il comando "docker cp" Uso: docker cp CONTENITORE: PERCORSO HOSTPATH ​​Copia i file / cartelle dal filesystem dei contenitori nel percorso host. I percorsi sono relativi alla radice del filesystem. #> docker cp 7bb0e258aefe: / etc / debian_version. #> docker cp blue_frog: / etc / hosts.
Amos Folarin,

4
L'opzione 4 è così importante che dovrebbe essere spostata in alto e rinominata Option 1.
automorfo

5
@JanusTroelsen Se non è presente alcuna shell, è possibile installarla, ad esempio nel dockerfile per linux alpino (che in effetti non ha shell) di: RUN apk update && apk add bash(dimensione: ~ 4 MB)
Kamil Kiełczewski,

2
per mia esperienza, la limitazione con il docker exec è che il comando deve essere aggiunto su un container in esecuzione o come una specie di entrypoint. Quindi un contenitore arrestato non rientra nell'ambito di questo metodo.
Webwoman,

1
Per usare la shell Linux di Windows usaredocker exec -t -i mycontainer /bin/sh
Jason Masters l'

266

AGGIORNAMENTO: ESPLORANDO!

Questo comando dovrebbe consentire di esplorare un container docker in esecuzione :

docker exec -it name-of-container bash

L'equivalente per questo in docker-compose sarebbe:

docker-compose exec web bash

(web è il nome del servizio in questo caso e ha tty per impostazione predefinita.)

Una volta dentro fai:

ls -lsa

o qualsiasi altro comando bash come:

cd ..

Questo comando dovrebbe consentire di esplorare un'immagine finestra mobile :

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

una volta dentro fai:

ls -lsa

o qualsiasi altro comando bash come:

cd ..

Lo -itsta per interattivo ... e tty.


Questo comando dovrebbe consentire di ispezionare un contenitore o un'immagine docker in esecuzione :

docker inspect name-of-container-or-image

Potresti voler fare questo e scoprire se ce ne sono bashosh dentro. Cerca entrypoint o cmd nel ritorno json.

vedere la documentazione del docker exec

consultare la documentazione exec di docker-compose

vedere la finestra di ispezione della finestra mobile


1
Questo è estremamente utile, grazie! Devo trascinare e rilasciare un file contenuto all'interno di una struttura di file immagine docker in un'applicazione, ma ciò non sarà possibile a meno che non venga aperto in un formato GUI. Hai idea di come potrei aggirare questo?
Arkya Chatterjee,

2
Dovrebbe essere abbastanza ovvio che questo funzionerà solo su un contenitore su cui è installato bash.
Software Engineer

2
Per chiunque cerchi come farlo su un contenitore / Powershell di Windows, il comando è docker exec -ti <name> powershell( sorgente )
ssell

1
@ssell il mio container / immagine non aveva powershell per qualche motivo, quindi ha docker exec -ti <name> cmdfunzionato. E per altri neofiti come me assicurati di usare il nome dell'istanza del contenitore da docker ps(qualcosa come 070494393ca5) piuttosto che il nome leggibile che gli hai assegnato.
Simon_Weaver,

1
per quanto riguarda powershell nelle immagini github.com/aspnet/aspnet-docker/issues/362 - e se hai solo bisogno di arricciare sulle immagini di Windows: blogs.technet.microsoft.com/virtualization/2017/12/19/…
Simon_Weaver

162

Nel caso in cui il contenitore sia arrestato o non abbia una shell (ad esempio hello-worldmenzionata nella guida all'installazione o non alpine traefik), questo è probabilmente l'unico metodo possibile per esplorare il filesystem.

È possibile archiviare il filesystem del proprio contenitore in un file tar:

docker export adoring_kowalevski > contents.tar

Oppure elenca i file:

docker export adoring_kowalevski | tar t

Si noti che, a seconda dell'immagine, potrebbero essere necessari del tempo e dello spazio su disco.


12
Volevo semplicemente elencare il contenuto di un contenitore in cui non sono installati strumenti UNIX standard. Una variante exportdell'esempio sopra ha colpito il punto:docker export adoring_kowalevski | tar tf -
berto

3
Un avvertimento per gli incauti: questo potrebbe esportare molti dati (> GB) e richiedere molto tempo.
Vince Bowdren,

5
@berto non che sia una cosa enorme, ma non dovresti aver bisogno f -alla fine del tuo comando, tar legge di default dallo standard input. docker export adoring_kowalevski | tar tFunziona semplicemente
Shaun Bouckaert,

Più semplice è, meglio è; fantastico, grazie per il suggerimento! 🙌🏽
berto

1
@ShaunBouckaert il valore predefinito tar fdipende dalla propria configurazione. Una parte è la TAPEvariabile d'ambiente. Altri sono controllati come parte della build. L'effetto netto è che non si dovrebbe mai presumere che legga stdin o scriva stdout ma lo affermi sempre esplicitamente.
roaima,

42

Il file system del contenitore si trova nella cartella dati della finestra mobile, normalmente in / var / lib / docker. Per avviare e ispezionare un file system dei contenitori in esecuzione, procedere come segue:

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

E ora la directory di lavoro corrente è la radice del contenitore.


3
questo non includerà comunque alcun volume montato.
hwjp,

34

Prima della creazione del contenitore:

Se puoi esplorare la struttura dell'immagine montata all'interno del contenitore, puoi farlo

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

Ciò ti darebbe la visibilità di tutti i livelli di un'immagine e la sua configurazione presente nei file json.

Dopo la creazione del contenitore:

Per questo ci sono già molte risposte sopra. il mio modo preferito per farlo sarebbe:

docker exec -t -i container /bin/bash


Va menzionato qui che l'esecuzione di bash all'interno del contenitore funziona solo se lo stai facendo su una macchina con la stessa architettura dell'immagine. Se sei su PC cercando di sbirciare nel filesystem di immagini di raspberry pi, il trucco bash non funzionerà.
Maxim Kulkin,

@MaximKulkin Davvero? Se il contenitore è Linux, non importa quale sia l'host, se bash è disponibile. Forse stai pensando ai contenitori di Windows?
Thorbjørn Ravn Andersen,

26

La risposta più votata funziona per me quando il contenitore è effettivamente avviato, ma quando non è possibile eseguirlo e tu, ad esempio, vuoi copiare i file dal contenitore, questo mi ha salvato prima:

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

Grazie alla docker cp ( link ) puoi copiare direttamente dal contenitore come qualsiasi altra parte del tuo filesystem. Ad esempio, ripristinare tutti i file all'interno di un contenitore:

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

Si noti che non è necessario specificare che si desidera copiare in modo ricorsivo.


6
perché questo non ha più +1? sicuramente il modo migliore
Nicholas DiPiazza

Questo è ancora più semplice dell'esportazione tramite tar. Ho dovuto usare -L per accedere ai file tramite symlink. Non è necessario eseguire il contenitore!
MKaama,

17

Su Ubuntu 14.04 che esegue Docker 1.3.1 , ho trovato il filesystem root del contenitore sul computer host nella seguente directory:

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

Informazioni sulla versione completa di 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

Funziona come un incantesimo: name = <name> dockerId = $ (docker inspect -f {{.Id}} $ name) / var / lib / docker / devicemapper / mnt / $ dockerId / rootfs /
Florent

3
Con Ubuntu 16.10 e docker 1.12.1 questo purtroppo non è più il caso (nessuna devicemapperdirectory). Il file esiste sotto /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/.... Non sono sicuro di quanto sia portatile / sicuro accedere ai file lì
WoJ

1
A partire dall'1.10, Docker ha introdotto un nuovo modello di archiviazione indirizzabile per i contenuti, che non utilizza l'UUID generato casualmente, come in precedenza sia per gli identificatori di layer che di container. Nel nuovo modello questo è sostituito da un hash di contenuto sicuro per ID layer. Quindi questo metodo non funzionerà più.
Artem Dolobanko,

Questo non è portatile e dipende fortemente dalla scelta del driver di archiviazione . Non sono sicuro se la soluzione funzionerà con direct-lvmad esempio.
Rustyx,

14

Prova a usare

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

Potrebbe esserci la possibilità che bash non sia implementato. per quello puoi usare

docker exec -it <container-name> sh

12

Uso un altro trucco sporco che è agnostico aufs / devicemapper.

Guardo il comando che il contenitore è in esecuzione ad es. docker ps E se è un apache o javafaccio semplicemente quanto segue:

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

e voilá sei dentro il container.

Fondamentalmente è possibile eseguire il root cd nella /proc/<PID>/root/cartella purché il processo sia eseguito dal contenitore. Attenzione, i collegamenti simbolici non avranno senso usando questa modalità.


Ulteriori informazioni su questo metodo qui: superuser.com/a/1288058/195840
Eduardo Lucio

12

La risposta più votata è buona tranne se il container non è un vero sistema Linux.

Molti contenitori (specialmente quelli basati su go) non hanno alcun binario standard (no /bin/basho/bin/sh ). In tal caso, dovrai accedere direttamente al file container effettivo:

Funziona come un fascino:

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

Nota: è necessario eseguirlo come root.


Questo non funziona più. La cartella devicemapper non è presente.
0xcaff,

Sarebbe bello se le persone con risposte obsolete li
ripulissero

2
Ho aggiornato il comando in modo che corrisponda alla nuova struttura di archiviazione della finestra mobile.
Florent,

10

Nel mio caso nessuna shell era supportata nel contenitore tranne sh. Quindi, ha funzionato come un fascino

docker exec -it <container-name> sh


5

Questo avvierà una sessione bash per l'immagine:

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


1
questo è utile per quando il punto di accesso predefinito non viene eseguito
parsethis

4

Per me, questo funziona bene (grazie agli ultimi commenti per aver indicato la directory / var / lib / docker / ):

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

Qui, 2465790aa2c4 è l'ID breve del contenitore in esecuzione (come visualizzato dalla finestra mobile ps ), seguito da una stella.


4

Nelle versioni più recenti di Docker è possibile eseguire docker exec [container_name]che esegue una shell all'interno del contenitore

Quindi per ottenere un elenco di tutti i file in un contenitore è sufficiente eseguirlo docker exec [container_name] ls


1
Ho provato questo e non ha funzionato. Il suggerimento di Khalil Gharbaoui sopra ha funzionato.
Nick,

Questo ha funzionato per me. Puoi anche provare con l'id contenitore invece del nome dell'immagine
Diwann

4

Per il driver docker aufs:

Lo script troverà la directory principale del contenitore (Test sulla finestra mobile 1.7.1 e 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

Nessuna delle risposte esistenti risolve il caso di un contenitore che è uscito (e non può essere riavviato) e / o non ha alcuna shell installata (ad esempio, quelle senza problemi). Questo funziona finché hai l'accesso root all'host Docker.

Per una vera ispezione manuale, scopri prima gli ID layer:

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

Nell'output, dovresti vedere qualcosa di simile

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

Passare a questa cartella (come root) per trovare lo stato visibile corrente del filesystem contenitore.


3

Questa risposta aiuterà coloro (come me) che vogliono esplorare il filesystem del volume docker anche se il container non è in esecuzione.

Elenco di contenitori docker in esecuzione:

docker ps

=> ID CONTENITORE "4c721f1985bd"

Guarda i punti di montaggio del volume della finestra mobile sulla tua macchina fisica locale ( https://docs.docker.com/engine/tutorials/dockervolumes/ ):

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

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

Questo mi dice che la directory della macchina fisica locale / tmp / container-garren è mappata sulla destinazione del volume della finestra mobile / tmp.

Conoscere la directory della macchina fisica locale (/ tmp / container-garren) significa che posso esplorare il filesystem indipendentemente dal fatto che il contenitore docker sia in esecuzione. Questo è stato fondamentale per aiutarmi a capire che c'erano alcuni dati residui che non avrebbero dovuto persistere anche dopo che il container non era in esecuzione.


1
Questo trova solo una directory locale che è montata come volume all'interno del contenitore ma non consente l'accesso all'intero file system del contenitore.
Bojan Komazec,

3

un altro trucco è usare lo strumento atomico per fare qualcosa del tipo:

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

L'immagine Docker verrà montata su / path / to / mnt per consentirne l' ispezione.


Ma devi avere contenitori appositamente realizzati per far funzionare tutto questo, giusto? Forse dovresti aggiungerlo come avvertimento, perché la maggior parte delle persone non sarà in grado di venderlo al proprio team / azienda come soluzione ...
Angelos Pikoulas

3

Solo per LINUX

Il modo più semplice che utilizzo è stato utilizzando proc dir, ovvero il contenitore deve essere in esecuzione per ispezionare i file del contenitore della finestra mobile.

  1. Scopri l'id di processo (PID) del contenitore e memorizza in alcune variabili

    PID = $ (docker inspect -f '{{.State.Pid}}' your-container-name-here)

  2. Assicurarsi che il processo contenitore sia in esecuzione e utilizzare la variabile nameto per accedere alla cartella contenitore

    cd / proc / $ PID / root

Se vuoi passare attraverso la dir senza scoprire il numero PID semplicemente usando questo lungo comando

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

Suggerimenti:

Dopo essere entrati nel contenitore, tutto ciò che fai influenzerà l'effettivo processo del contenitore, come l'arresto del servizio o la modifica del numero di porta.

Spero che sia d'aiuto

Nota:

Questo metodo funziona solo se il contenitore è ancora in esecuzione, altrimenti la directory non esisterebbe più se il contenitore si è arrestato o rimosso


2

Il mio modo preferito per capire cosa sta succedendo all'interno del container è:

  1. esporre -p 8000

    docker run -it -p 8000:8000 image
    
  2. Avvia il server al suo interno

    python -m SimpleHTTPServer
    

2

Per un contenitore già in esecuzione, puoi fare:

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

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

Devi essere root per poter inserire cd in quella directory. Se non si è root, provare 'sudo su' prima di eseguire il comando.

Modifica: dopo v1.3, vedi la risposta di Jiri - è meglio.


4
Sono fortemente parziale a "sudo -i" piuttosto che a "sudo su" perché ci sono poche ragioni per eseguire un programma suid che avvia un altro programma suid che avvia una shell. Taglia l'uomo di mezzo. :)
dannysauer,

La tua risposta è molto buona, solo il percorso non lo è. Dovresti usare il percorso di piercebot.
Florent,

2

Se si utilizza Docker v19.03, seguire i passaggi seguenti.

# 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

Se si utilizza il driver di archiviazione AUFS, è possibile utilizzare il mio script a livello di finestra mobile per trovare il root del filesystem (mnt) di qualsiasi contenitore e il livello readwrite:

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

Modifica 28-03-2018: il docker
-layer è stato sostituito dal docker-backup


1

Il docker execcomando per eseguire un comando in un contenitore in esecuzione può aiutare in più casi.

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

Esegui un comando in un contenitore in esecuzione

Opzioni:
  -d, --detach Modalità indipendente: esegue il comando in background
      --detach-keys string Sostituisce la sequenza di tasti per staccare a
                             contenitore
  -e, --env list Imposta le variabili di ambiente
  -i, --interattivo Tenere aperto STDIN anche se non collegato
      --privileged Assegna privilegi estesi al comando
  -t, --tty Assegna uno pseudo-TTY
  -u, --user stringa Nome utente o UID (formato:
                             [:])
  -w, --workdir stringa Directory di lavoro all'interno del contenitore

Per esempio :

1) Accesso in bash al filesystem del container in esecuzione:

docker exec -it containerId bash 

2) Accedere in bash al filesystem del container in esecuzione come root per poter avere i diritti richiesti:

docker exec -it -u root containerId bash  

Ciò è particolarmente utile per essere in grado di eseguire alcune elaborazioni come root in un contenitore.

3) Accesso in bash al filesystem del container in esecuzione con una directory di lavoro specifica:

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

0

È possibile eseguire un bash all'interno del contenitore con questo: $ docker run -it ubuntu /bin/bash

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.