Поиск по сайту:

Как проверить изменения в файловой системе контейнера Docker


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

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

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

Использование Docker Diff

Для этого в Docker CLI есть встроенная команда. Запуск docker diff перечислит все изменения, внесенные в файлы и каталоги в конкретном контейнере. Он принимает идентификатор или имя контейнера, который вы хотите проверить.

Запустите простой контейнер для демонстрационных целей:

$ docker run -it --name alpine alpine:latest sh

Это запустит новый контейнер с изображением Alpine. Окно вашего терминала будет прикреплено к контейнеру. Держите это окно открытым.

Теперь запустите docker diff во втором сеансе терминала:

$ docker diff alpine

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

Вернитесь к своему первому терминалу, который все еще подключен к контейнеру. Запустите несколько команд, которые добавляют, удаляют или изменяют файлы:

/ # touch demo
/ # touch example

Вернитесь к первому окну оболочки. Повторите команду docker diff, чтобы увидеть внесенные изменения:

$ docker diff alpine
A /example
C /root
C /root/.ash_history
A /demo

Теперь два новых файла видны в выводе команды. Запуск touch также добавил записи в историю оболочки контейнера. Также сообщается об изменении /root/.ash_history, а также о последующем изменении каталога /root.

Интерпретация вывода Docker Diff

Каждая строка вывода, создаваемая docker diff, имеет префикс A, C или D в зависимости от типа произошло изменение:

  • A — файл или каталог добавлен в файловую систему контейнера. Его нет на исходном изображении.
  • C — содержимое файла или каталога отличается от версии на изображении.
  • D – путь, присутствующий в изображении, удален из контейнера.

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

Любые изменения файловой системы, которые не отображаются в выходных данных, повлияют на пути, сопоставленные с томом Docker. Эти файлы хранятся вне контейнера, независимо от его файловой системы, поэтому они не отображаются с помощью docker diff.

Просмотр содержимого в исходном изображении

Может быть полезно сравнить версию файла, которая включена в исходное изображение. Вы можете сделать это, создав новый контейнер, а затем скопировав файл. Используйте docker create вместо docker run, чтобы контейнер был создан, но не запущен. Это гарантирует, что изменения, вызванные сценарием точки входа изображения, не повлияют на результат.

$ docker create --name temp-container my-image:latest
$ docker cp temp-container:/path/to/file copied-file
$ docker rm temp-container

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

$ docker run --rm --entrypoint cat alpine:latest /path/to/file > copied-file

Сравнение различий между двумя контейнерами

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

$ docker diff first-container > first
$ docker diff second-container > second

Теперь вы можете использовать стандартные инструменты Unix, такие как команда diff, чтобы найти различия в двух списках изменений:

diff first second
3c3
< A /a-new-file
---
> A /demo

Разница показывает, что /a-new-file был удален во втором контейнере, а /demo был добавлен.

Другой способ сравнить контейнеры — использовать docker export и команду tar для доступа к полному списку файлов:

$ docker export demo-container | tar tv
-rwxr-xr-x 0/0               0 2022-06-21 14:21 .dockerenv
drwxr-xr-x 0/0               0 2022-05-23 17:51 bin/
lrwxrwxrwx 0/0               0 2022-05-23 17:51 bin/arch -> /bin/busybox
lrwxrwxrwx 0/0               0 2022-05-23 17:51 bin/ash -> /bin/busybox
lrwxrwxrwx 0/0               0 2022-05-23 17:51 bin/base64 -> /bin/busybox
lrwxrwxrwx 0/0               0 2022-05-23 17:51 bin/bbconfig -> /bin/busybox
...

Повторите эту команду для обоих контейнеров. Затем вы можете использовать diff для сравнения двух списков. Расширенный вывод tar может помочь вам отследить, когда файлы были изменены, поскольку отображаются время модификации и разрешения.

Краткое содержание

Файловые системы контейнеров Docker должны очень напоминать образ, из которого они были созданы. Расхождения могут возникать, когда программное обеспечение внутри контейнера записывает содержимое непосредственно в файловую систему. Пользователи могут быть еще одним источником различий, когда такие механизмы, как docker exec, используются для запуска команд в работающем контейнере.

Утилита docker diff предоставляет удобный способ просмотра этих изменений. Хотя вы не можете видеть, почему файл был добавлен или удален, возможность получить список модификаций может оказаться бесценной для понимания того, почему наблюдается конкретное поведение.

В этой статье мы сосредоточились на изучении изменений, внесенных в работающие контейнеры. Вы можете использовать различные инструменты, такие как docker history и Dive, для проверки изменений, внесенных в слои в образе Docker. Эти два подхода можно использовать в тандеме, что позволяет определить точную точку, в которой файл был добавлен или изменен в стеке слоев контейнера.