Перейти к основному содержимому

Изучение файловой системы контейнера Docker

· 6 мин. чтения

1. Обзор

Когда мы работаем с Docker, иногда нам нужно проверить файлы конфигурации или журналы внутри контейнера.

В этом кратком руководстве мы увидим, как проверить файловую систему контейнера Docker, чтобы помочь нам решить такие ситуации.

2. Интерактивное исследование

Мы можем исследовать файловую систему в интерактивном режиме для большинства контейнеров, если получим к ним доступ из оболочки.

2.1. Запуск контейнера с доступом к оболочке

Запустим контейнер напрямую с доступом к оболочке с помощью команды запуска docker с параметром -it :

$ docker run -it alpine
/# ls -all
...
-rwxr-xr-x 1 root root 0 Mar 5 13:21 .dockerenv
drwxr-xr-x 1 root root 850 Jan 16 21:52 bin
drwxr-xr-x 5 root root 360 Mar 5 13:21 dev
drwxr-xr-x 1 root root 508 Mar 5 13:21 etc
drwxr-xr-x 1 root root 0 Jan 16 21:52 home
....

Здесь мы запустили контейнер Alpine Linux в интерактивном режиме и подключились к его оболочке.

Но что произойдет, если мы захотим исследовать что-то, что не является дистрибутивом Linux?

$ docker run -it cassandra
...
INFO [MigrationStage:1] 2020-03-05 13:44:36,734 - Initializing system_auth.resource_role_permissons_index
INFO [MigrationStage:1] 2020-03-05 13:44:36,739 - Initializing system_auth.role_members
INFO [MigrationStage:1] 2020-03-05 13:44:36,743 - Initializing system_auth.role_permissions
INFO [MigrationStage:1] 2020-03-05 13:44:36,747 - Initializing system_auth.roles
INFO [main] 2020-03-05 13:44:36,764 - Waiting for gossip to settle...
...

Докер-контейнер Cassandra поставляется с командой запуска по умолчанию, которая запускает Cassandra. В результате мы больше не связаны с оболочкой.

Вместо этого мы просто видим стандартный вывод, заполненный сообщениями журнала приложения.

Однако мы можем обойти команду запуска по умолчанию.

Давайте передадим дополнительный аргумент /bin/bash в команду запуска docker :

$ docker run -it cassandra /bin/bash
root@a71f71e98598:/# ls -all
total 4
...
-rwxr-xr-x 1 root root 0 Mar 5 13:30 .dockerenv
drwxr-xr-x 1 root root 920 Aug 14 2019 bin
drwxr-xr-x 1 root root 0 Mar 28 2019 boot
drwxr-xr-x 5 root root 360 Mar 5 13:30 dev
lrwxrwxrwx 1 root root 34 Aug 14 2019 docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
drwxr-xr-x 1 root root 1690 Mar 5 13:30 etc
...

К сожалению, это имеет неприятный побочный эффект. Собственно приложение Cassandra больше не запускается, и нам приходится делать это вручную из оболочки.

Когда мы используем этот подход, мы предполагаем, что можем контролировать запуск контейнера. В производственной среде это может быть невозможно.

2.2. Создание оболочки в работающем контейнере

К счастью, мы можем использовать команду docker exec , которая позволяет нам подключаться к работающим контейнерам .

Давайте сначала запустим контейнер, который мы хотим исследовать:

$ docker run cassandra
...
INFO [MigrationStage:1] 2020-03-05 13:44:36,734 - Initializing system_auth.resource_role_permissons_index
INFO [MigrationStage:1] 2020-03-05 13:44:36,739 - Initializing system_auth.role_members
INFO [MigrationStage:1] 2020-03-05 13:44:36,743 - Initializing system_auth.role_permissions
INFO [MigrationStage:1] 2020-03-05 13:44:36,747 - Initializing system_auth.roles
INFO [main] 2020-03-05 13:44:36,764 - Waiting for gossip to settle...
...

Затем мы идентифицируем идентификатор контейнера с помощью docker ps :

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
00622c0645fb cassandra "docker-entrypoint.s…" 2 minutes ago

Затем мы передаем /bin/bash в качестве аргумента с опцией -it для docker exec :

$ docker exec -it 00622c0645fb /bin/bash
root@00622c0645fb:/# ls -all
...
-rwxr-xr-x 1 root root 0 Mar 5 13:44 .dockerenv
drwxr-xr-x 1 root root 920 Aug 14 2019 bin
drwxr-xr-x 1 root root 0 Mar 28 2019 boot
drwxr-xr-x 5 root root 340 Mar 5 13:44 dev
lrwxrwxrwx 1 root root 34 Aug 14 2019 docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh
drwxr-xr-x 1 root root 1690 Mar 5 13:44 etc
...

Здесь мы использовали Bash в качестве предпочтительной оболочки . Это может варьироваться в зависимости от того, на каком дистрибутиве Linux основан контейнер.

Напротив, в нашем первом примере используется Alpine Linux, который по умолчанию поставляется с Bourne Shell:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
8408c85b3c57 alpine "/bin/sh" 3 seconds ago

Поскольку Bash недоступен, мы передаем /bin/sh в качестве аргумента для docker exec :

$ docker exec -it 8408c85b3c57 /bin/sh
/ # ls -all
...
-rwxr-xr-x 1 root root 0 Mar 5 14:19 .dockerenv
drwxr-xr-x 1 root root 850 Jan 16 21:52 bin
drwxr-xr-x 5 root root 340 Mar 5 14:19 dev
drwxr-xr-x 1 root root 508 Mar 5 14:19 etc
drwxr-xr-x 1 root root 0 Jan 16 21:52 home
...

3. Неинтерактивное исследование

Иногда контейнер останавливается, и мы не можем запустить его в интерактивном режиме, или у него просто нет оболочки.

Например, hello-world — это минимальный контейнер, который начинается с нуля . В результате доступ к оболочке невозможен.

К счастью для нас, в обеих ситуациях мы можем сделать дамп файловой системы на наш хост-компьютер для дальнейшего изучения.

Давайте посмотрим, как мы можем это сделать.

3.1. Экспорт файловой системы

Мы можем экспортировать файловую систему контейнера в файл tar с помощью команды экспорта docker .

Давайте сначала запустим контейнер hello-world:

$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
....

Точно так же мы сначала получаем идентификатор контейнера остановленного контейнера, передавая флаг -a в docker ps :

$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
a0af60c72d93 hello-world "/hello" 3 minutes ago
...

Затем мы выгружаем файловую систему в файл hello.tar, используя опцию -o экспорта докеров :

$ docker export -o hello.tar a0af60c72d93

Наконец, печатаем содержимое архива с помощью утилиты tar с флагами -tvf :

$ tar -tvf hello.tar
-rwxr-xr-x root/0 0 2020-03-05 16:55 .dockerenv
....
drwxr-xr-x root/0 0 2020-03-05 16:55 dev/pts/
drwxr-xr-x root/0 0 2020-03-05 16:55 dev/shm/
....
-rwxr-xr-x root/0 0 2020-03-05 16:55 etc/resolv.conf
-rwxrwxr-x root/0 1840 2019-01-01 03:27 hello
...

Кроме того, мы можем использовать любой архиватор, чтобы посмотреть, что внутри.

3.2. Копирование файловой системы

Мы также можем скопировать всю файловую систему с помощью команды docker cp .

Попробуем и это.

Сначала мы копируем всю файловую систему, начиная с корня (/) , из нашего контейнера в тестовый каталог:

$ docker cp a0af60c72d93:/ ./test

Далее, давайте распечатаем содержимое тестового каталога:

$ ls -all test/
total 28
..
drwxr-xr-x 4 foreach users 4096 Mar 5 16:55 dev
-rwxr-xr-x 1 foreach users 0 Mar 5 16:55 .dockerenv
drwxr-xr-x 2 foreach users 4096 Mar 5 16:55 etc
-rwxrwxr-x 1 foreach users 1840 Jan 1 2019 hello

4. Вывод

В этом кратком руководстве мы обсудили, как исследовать файловую систему контейнера Docker.

Мы можем запускать большинство контейнеров с доступом к оболочке напрямую с помощью команды запуска docker . Кроме того, мы можем создать оболочку для запуска контейнеров с помощью docker exec.

Когда дело доходит до остановленных контейнеров или минимальных контейнеров, мы можем просто экспортировать или даже локально скопировать всю файловую систему.