«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
[email protected]:/# 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 option для docker exec:

$ docker exec -it 00622c0645fb /bin/bash
[email protected]:/# 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 с помощью опции экспорта docker -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 baeldung users 4096 Mar  5 16:55 dev
-rwxr-xr-x  1 baeldung users    0 Mar  5 16:55 .dockerenv
drwxr-xr-x  2 baeldung users 4096 Mar  5 16:55 etc
-rwxrwxr-x  1 baeldung users 1840 Jan  1  2019 hello

4. Заключение

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

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

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