Вивчення файлової системи контейнера Docker


651

Я помітив за допомогою docker, що мені потрібно зрозуміти, що відбувається всередині контейнера або які файли там є. Один із прикладів - завантаження зображень з індексу докера - у вас немає поняття, що містить зображення, тому неможливо запустити програму.

Що було б ідеально - це вміти врізатися в них або подібних до них. Чи є інструмент для цього чи моя концептуалізація докера неправильна в думці, я повинен бути в змозі це зробити.


13
В останніх версіях Докер, що - то , як це можливо: docker exec <container> bash. Отже, ви просто відкриєте оболонку всередині контейнера.
dashohoxha

7
запуск bash на контейнері працює лише в тому випадку, якщо bash встановлений всередині контейнера
Christopher Thomas

7
Аналогічно можна зробити: docker exec <container> ls <dir path>і docker exec <container> cat <file path>. Для bash, однак, додайте -itпараметри.
Ноам Манос

Схожий питання: stackoverflow.com/questions/44769315 / ...
Vadzim

3
@ChristopherThomas, точно. Через це я виявив, що єдиний надійний спосіб зробити це, docker image save image_name > image.tarяк зазначено у відповіді від @ Gaurav24.
Хайме Хаблуцель

Відповіді:


736

ОНОВЛЕННЯ
Найпростіший метод: Використання docker exec

Docker версії 1.3 або новішої підтримує команду, execяка поводиться аналогічно nsenter. Ця команда може запустити новий процес у вже запущеному контейнері (у контейнері вже повинен бути запущений процес PID 1). Ви можете запустити /bin/bashдля вивчення стану контейнера:

docker exec -t -i mycontainer /bin/bash

див. документацію до командного рядка Docker

Альтернативний метод 1
Знімок

Ви можете оцінити файлову систему контейнера таким чином:

# 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

Таким чином, ви можете оцінити файлову систему запущеного контейнера в точний момент часу. Контейнер все ще запущений, майбутні зміни не включаються.

Пізніше ви можете видалити знімок за допомогою (файлова система запущеного контейнера не впливає!):

docker rmi mysnapshot

Альтернативний метод 2
сш

Якщо вам потрібен постійний доступ, ви можете встановити sshd у свій контейнер і запустити демон sshd:

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

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

Таким чином, ви можете запустити свою програму за допомогою ssh (підключіть та виконайте те, що ви хочете).

ОНОВЛЕННЯ: Альтернативний метод 3
нецензури

Використовуйте nsenterдивіться https://web.archive.org/web/20160305150559/http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/

Коротка версія: за допомогою nsenter ви можете отримати оболонку в існуючий контейнер, навіть якщо в цьому контейнері не працює SSH або будь-який демон спеціального призначення


6
але зверніть увагу, якщо вам потрібен доступ до файлів, використовуйте команду "docker cp" Використання: docker cp КОНТЕЙНЕР: PATH HOSTPATH ​​Скопіюйте файли / папки з файлової системи контейнерів на шлях хосту. Шляхи відносно кореня файлової системи. #> docker cp 7bb0e258aefe: / etc / debian_version. #> docker cp blue_frog: / etc / hosts.
Амос Фоларін

4
Варіант 4 настільки важливий, що його слід перемістити до верху та перейменувати Option 1.
automorphic

5
@JanusTroelsen Якщо немає оболонки, ви можете встановити її - наприклад, в dockerfile для альпійського Linux (у якого справді немає оболонки) за RUN apk update && apk add bash
Kamil Kiełczewski

2
на моєму власному досвіді обмеження у Docker exec полягає в тому, що команду потрібно додати до запущеного контейнера або як певної точки входу. Отже, зупинений контейнер виходить за межі цього методу.
Веб-жінка

1
Для використання linux-оболонки Windowdocker exec -t -i mycontainer /bin/sh
Jason Masters

266

ОНОВЛЕННЯ: ДОСЛІДЖЕННЯ!

Ця команда повинна дозволити вивчити запущений контейнер докера :

docker exec -it name-of-container bash

Еквівалентом цього в docker-compose було б:

docker-compose exec web bash

(web - це ім'я служби в цьому випадку, і він має tty за замовчуванням.)

Коли ви всередині, зробіть:

ls -lsa

або будь-яка інша команда bash, наприклад:

cd ..

Ця команда повинна дозволити вивчити зображення докера :

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

як тільки всередині:

ls -lsa

або будь-яка інша команда bash, наприклад:

cd ..

-itЧи означає інтерактивний ... і термінал.


Ця команда повинна дозволити вам перевірити запущений контейнер або зображення докера :

docker inspect name-of-container-or-image

Ви можете зробити це і дізнатись, чи є там bashчи shтам. Шукайте точку входу або cmd у поверненні json.

дивіться документацію докер-виконавця

перегляньте документацію на виконання докер-композиції

див. документацію для перевірки докерів


1
Це надзвичайно корисно, дякую! Мені потрібно перетягнути файл, який міститься в структурі файлів зображення докер-файлу, у додаток, але це неможливо, якщо він не буде відкритий у форматі GUI. Будь-яка ідея, як я міг обійти це?
Arkya Chatterjee

2
Це повинно бути досить очевидним, що це буде працювати тільки на контейнері, на якому встановлений bash.
програмний інженер

2
Для всіх, хто дивиться на те, як це зробити на Windows Container / Powershell, команда docker exec -ti <name> powershell( джерело )
ssell

1
@ssell мій контейнер / зображення чомусь не було повноважень, тому це docker exec -ti <name> cmdспрацювало. А для інших новачків, як я, обов'язково використовуйте ім'я екземпляра контейнера docker ps(щось на зразок 070494393ca5), а не читабельне ім'я, яке ви призначили.
Simon_Weaver

1
відносно повноважень у зображеннях github.com/aspnet/aspnet-docker/isissue/362 - і якщо вам потрібен лише завиток на зображеннях Windows: blogs.technet.microsoft.com/virtualization/2017/12/19/…
Simon_Weaver

162

У випадку, якщо ваш контейнер зупинений або не має оболонки (наприклад, hello-worldзгадується в посібнику з встановлення , або не alpine traefik), це, мабуть, єдиний можливий метод дослідження файлової системи.

Ви можете архівувати файлову систему вашого контейнера у файл tar:

docker export adoring_kowalevski > contents.tar

Або перерахуйте файли:

docker export adoring_kowalevski | tar t

Зауважте, що залежно від зображення, це може зайняти деякий час і диск на диску.


12
Я просто хотів перерахувати вміст контейнера, на якому не встановлено стандартних інструментів UNIX. Варіант exportприкладу вище потрапив на місце:docker export adoring_kowalevski | tar tf -
Берто

3
Попередження для необережних: це може експортувати багато даних (> ГБ) і зайняти багато часу.
Вінс Боудрен

5
@berto не те, що це велика річ, але вам не потрібно f -в кінці вашої команди, tar за замовчуванням читає зі стандартного вводу. Просто docker export adoring_kowalevski | tar tпрацює.
Shaun Bouckaert

Чим простіше, тим краще; приголомшливий, дякую за пораду! 🙌🏽
Берто

1
@ShaunBouckaert за замовчуванням tar fзалежить від конфігурації. Одна частина - це TAPEзмінна середовище. Інші контролюються як частина збірки. Чистий ефект полягає в тому, що ніколи не слід вважати, що він читає stdin або пише stdout, а завжди чітко заявляє про це.
roaima

42

Файлова система контейнера знаходиться в папці даних докера, як правило, в / var / lib / docker. Для запуску та перевірки працюючої файлової системи контейнерів виконайте наступне:

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

І тепер поточний робочий каталог є коренем контейнера.


3
це не буде включати жодних змонтованих томів.
hwjp

34

Перед створенням контейнера:

Якщо ви вивчите структуру зображення, встановленого всередині контейнера, ви можете це зробити

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

Це дасть вам видимість усіх шарів зображення та його конфігурації, яка присутня у файлах json.

Після створення контейнера:

На це вище вже є багато відповідей. мій кращий спосіб зробити це -

docker exec -t -i container /bin/bash


Тут слід зазначити, що запуск bash всередині контейнера працює лише в тому випадку, якщо ви робите це на машині з тією ж архітектурою, що і зображення. Якщо ви працюєте на ПК, намагаючись зазирнути у файлову систему зображень малинового пі, трюк bash не спрацює.
Максим Кулкін

@MaximKulkin Дійсно? Якщо контейнер Linux, це не має значення, що хост, якщо bash доступний. Можливо, ви думаєте про контейнери Windows?
Thorbjørn Ravn Andersen

26

Найбільш актуальна відповідь працює для мене, коли контейнер насправді запущений, але коли неможливо запустити, і ви, наприклад, хочете скопіювати файли з контейнера, це врятувало мене раніше:

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

Завдяки docker cp ( посилання ) ви можете скопіювати безпосередньо з контейнера, як це була будь-яка інша частина вашої файлової системи. Наприклад, відновлення всіх файлів всередині контейнера:

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

Зауважте, що вам не потрібно вказувати, що потрібно копіювати рекурсивно.


6
чому цього більше немає +1! безумовно найкращий спосіб
Ніколас ДіПіаца

Це навіть простіше, ніж експорт за допомогою дьогтю. Мені довелося використовувати -L, щоб дістатися до файлів за допомогою посилань. Не потрібно запускати контейнер!
MKaama

17

У Ubuntu 14.04 під керуванням Docker 1.3.1 я знайшов кореневу файлову систему контейнера на хост-машині в наступному каталозі:

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

Повна інформація про версію Докера:

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

Працює як шарм: name = <ім'я> dockerId = $ (docker inspect -f {{.Id}} $ name) / var / lib / docker / devicemapper / mnt / $ dockerId / rootfs /
Florent

3
З Ubuntu 16.10 та docker 1.12.1, на жаль, це вже не так (немає devicemapperкаталогу). Файл існує під /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/.... Я не впевнений, наскільки портативний / безпечний доступ до файлів там
WoJ

1
Починаючи з 1.10, Docker представив нову модель зберігання, адресовану вмістом, яка не використовує випадково створений UUID, як це було раніше для ідентифікаторів шару та контейнерів. У новій моделі це замінено захищеним хешем вмісту для ідентифікатора шару. Тож цей метод більше не буде працювати.
Артем Долобанко

Це не портативно і значною мірою залежить від вибору драйвера зберігання . Не впевнений, чи працює рішення, direct-lvmнаприклад.
rustyx

14

Спробуйте використовувати

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

Можливо, існує можливість, що bash не буде реалізований. для цього ви можете скористатися

docker exec -it <container-name> sh

12

Я використовую ще один брудний трюк - це aufs / devicemapper agnostic.

Я дивлюсь на команду про те, що контейнер працює, наприклад, docker ps і якщо це apache або javaя просто виконую наступні дії:

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

і voilá ти всередині контейнера.

В основному ви можете як root CD в /proc/<PID>/root/папку, поки цей процес запускається контейнером. Обережно, що посилання на цей режим не матимуть сенсу підступно.


Додаткова інформація про цей метод тут: superuser.com/a/1288058/195840
Eduardo Lucio

12

Відповідь, яка найбільше голосує, хороша за винятком випадків, якщо ваш контейнер не є фактичною системою Linux.

У багатьох контейнерах (особливо на базі даних) немає стандартних бінарних файлів (немає /bin/bashабо /bin/sh). У цьому випадку вам потрібно буде отримати доступ до фактичного файлу контейнерів безпосередньо:

Працює як шарм:

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

Примітка. Вам потрібно запустити його як root.


Це більше не працює. Папки devicemapper немає.
0xcaff

Було б добре, якби люди з застарілими відповідями очистили їх
Меттью Пердон

2
Я оновив команду, щоб відповідати новій структурі зберігання докера.
Флорент

10

У моєму випадку жодна оболонка не підтримувалася, крім sh. Отже, це спрацювало як шарм

docker exec -it <container-name> sh


5

Це запустить сеанс bash для зображення:

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


1
це корисно для тих випадків, коли точка вводу за замовчуванням не запускається
проаналізуйте

4

Для мене це добре працює (завдяки останнім коментарям до вказівки на каталог / var / lib / docker / ):

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

Тут 2465790aa2c4 - короткий ідентифікатор запущеного контейнера (як показано докерним ps ), за яким слід зірка.


4

У нових версіях Docker ви можете запустити, docker exec [container_name]який запускає оболонку всередині вашого контейнера

Отже, щоб отримати список усіх файлів у контейнері, просто запустіть docker exec [container_name] ls


1
Я спробував це, і це не вийшло. Пропозиція Халила Гарбауї вище спрацювала.
Нік

Це працювало для мене. Ви також можете спробувати ідентифікатор контейнера замість назви зображення
Diwann

4

Для драйвера aucker aufs:

Сценарій знайде кореневу діру контейнера (Тест на докер 1.7.1 та 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

Жодна з існуючих відповідей не стосується випадку контейнера, який вийшов (і не може бути перезапущений) та / або не має встановленої оболонки (наприклад, безвідмовної). Цей працює, поки у вас є кореневий доступ до хоста Docker.

Для справжнього ручного огляду спочатку з’ясуйте ідентифікатори шару:

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

У висновку ви повинні побачити щось подібне

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

Перейдіть у цю папку (як root), щоб знайти поточний видимий стан файлової системи контейнера.


3

Ця відповідь допоможе тим (як я), які хочуть дослідити файлову систему тома докера, навіть якщо контейнер не працює.

Перерахуйте запущені контейнери докера:

docker ps

=> ІД КОНТЕЙНЕР "4c721f1985bd"

Погляньте на точки кріплення гучності докера на локальній фізичній машині ( https://docs.docker.com/engine/tutorials/dockervolumes/ ):

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

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

Це говорить мені про те, що каталог локальної фізичної машини / tmp / контейнер-гаррен відображається в пункт призначення тома докера / tmp.

Знаючи довідник локальної фізичної машини (/ tmp / container-garren), це означає, що я можу дослідити файлову систему, чи працює контейнер докера чи ні. Це було надзвичайно важливим, щоб допомогти мені зрозуміти, що є деякі залишкові дані, які не повинні зберігатися навіть після того, як контейнер не запускався.


1
Це лише знаходить локальний каталог, який встановлений як об'єм всередині контейнера, але не дозволяє отримати доступ до всієї файлової системи контейнера.
Bojan Komazec

3

Ще одна хитрість - використовувати атомний інструмент, щоб зробити щось на кшталт:

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

Зображення Докера буде встановлено на / path / to / mnt, щоб ви його оглянули.


Але для цього вам потрібно мати спеціально виготовлені контейнери, правда? Можливо, вам слід додати це як застереження, бо більшість людей не зможуть продати його своїй команді / компанії як рішення ...
Angelos Pikoulas

3

Тільки для LINUX

Найпростішим способом, яким я користуюся, було використання proc dir, який є контейнером, має бути запущений, щоб перевірити файли контейнерів docker.

  1. Дізнайтеся ідентифікатор процесу (PID) контейнера та збережіть у деякій змінній

    PID = $ (докер перевіряє -f '{{.State.Pid}}' your-container-name-here)

  2. Переконайтеся, що процес контейнера запущений, і використовуйте змінну nameto, щоб потрапити в папку контейнера

    cd / proc / $ PID / root

Якщо ви хочете пройти через dir, не дізнавшись номер PID, просто скориставшись цією довгою командою

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

Поради:

Після того, як ви потрапите всередину контейнера, все, що ви зробите, вплине на фактичний процес контейнера, як-от зупинка служби або зміна номера порту.

Сподіваюся, це допомагає

Примітка:

Цей метод працює лише в тому випадку, якщо контейнер все ще працює, інакше каталог більше не існуватиме, якщо контейнер зупинився або видалений


2

Мій кращий спосіб зрозуміти, що відбувається всередині контейнера:

  1. виставити -p 8000

    docker run -it -p 8000:8000 image
    
  2. Запустіть сервер всередині нього

    python -m SimpleHTTPServer
    

2

Для вже запущеного контейнера ви можете:

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

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

Потрібно мати корінь для того, щоб вступити в цей dir. Якщо ви не root, спробуйте 'sudo su' перед запуском команди.

Редагувати: Після версії 1.3 перегляньте відповідь Джирі - краще.


4
Я сильно частковий до "sudo -i", а не до "sudo su", тому що мало підстав запускати програму suid, яка запускає іншу програму suid, яка запускає оболонку. Виріжте середнього чоловіка. :)
dannysauer

Ваша відповідь дуже хороша, тільки шлях не є. Ви повинні використовувати шлях piercebot.
Флорент

2

Якщо ви використовуєте Docker v19.03, виконайте наведені нижче дії.

# 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, ви можете використовувати мій докер-шар сценарій щоб знайти корінь файлової системи будь-якого контейнера (mnt) та шар перезапису:

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

Редагувати 2018-03-28: Докер
-шар замінено докер-резервним


1

docker execКоманди для запуску команди в робочому контейнері може допомогти в декількох випадках.

Використання: docker exec [ВАРІАНТИ] CONTAINER COMMAND [ARG ...]

Виконайте команду в запущеному контейнері

Параметри:
  -d, --встановити окремий режим: запустити команду у фоновому режимі
      --detach-рядок-ключі Заміняє послідовність клавіш для від'єднання a
                             контейнер
  -e, --env list Встановити змінні середовища
  -i, - інтерактивне Тримайте STDIN відкритим, навіть якщо він не встановлений
      --privileged Дайте розширені привілеї команді
  -t, --tty Виділіть псевдо-TTY
  -u, - рядоккористувача Ім'я користувача або UID (формат:
                             [:])
  -w, --workdir string Робочий каталог всередині контейнера

Наприклад :

1) Доступ в bash до запущеної файлової системи контейнера:

docker exec -it containerId bash 

2) Доступ в bash до запущеної файлової системи контейнерів як root, щоб мати необхідні права:

docker exec -it -u root containerId bash  

Це особливо корисно, щоб можна було виконати деяку обробку як корінь у контейнері.

3) Доступ в bash до запущеної файлової системи контейнерів із певним робочим каталогом:

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

0

Ви можете запустити bash всередині контейнера за допомогою цього: $ docker run -it ubuntu /bin/bash

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.