Печать количества файлов без учета каталогов

Is there a way (or several ways) to retrieve from the image, the contents of file.txt that was added then removed in an intermediate layer?

Да!

Does the answer depend on the choice of the WORKDIR?

Нет. WORKDIRне делает ничего, кроме изменения текущего рабочего каталога.


Когда вы создаете образ из Dockerfile, каждая директива в Dockerfile создает новый слой. «Образ» — это просто набор слоев, которые объединяются для формирования файловой системы контейнера при запуске контейнера. Каждый из этих слоев можно найти отдельно на вашем диске в /var/lib/docker. Например, предположим, что я создаю образ, используя этот Dockerfile:

FROM debian:9
COPY file.txt /root/file.txt
RUN rm -f /root/file.txt

В этом каталоге у меня есть файл с именем file.txt, который содержит текст:

hello world

Если я побегу docker build -t erikmd., я увижу:

Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM debian:9
 ---> d508d16c64cd
Step 2/3 : COPY file.txt /root/file.txt
 ---> Using cache
 ---> 6f06029c1cca
Step 3/3 : RUN rm -f /root/file.txt
 ---> Using cache
 ---> a2dc62c823c9
Successfully built a2dc62c823c9
Successfully tagged erikmd:latest

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

$ docker run --rm 6f06029c1cca cat /root/file.txt

И посмотреть содержимое файла:

hello world

Но что, если я не просто построил образ? В этом случае я бы начал с использования команды docker image inspectдля просмотра списка слоев, составляющих изображение :

.
$ docker image inspect erikmd | jq '.[0].RootFS.Layers'
[
  "sha256:13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303",
  "sha256:41494b03ef195ce6db527bd68b89cbebdace66210b4c142e95f8553fcb0bf51e",
  "sha256:1948a4bd00b6f1712667bb2c68d1fe6eb60fbbcdf8bad62653208c23bf2602a5"
]

В приведенном выше примере jq— это просто инструмент для запроса данных JSON. Вы можете просто визуально проверить вывод docker image inspectдля получения той же информации, если у вас нет под рукой jq.

Предполагая, что конфигурация Docker по умолчанию использует драйвер хранилища overlay2, вы найдете эти идентификаторы в /var/lib/docker/image/overlay2/layerdb/sha256/*/diff. Так, например:

# grep -l 13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303 \
  /var/lib/docker/image/overlay2/layerdb/sha256/*/diff
/var/lib/docker/image/overlay2/layerdb/sha256/13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303/diff

Этот первый слой является изображением debian:9. Мы можем подтвердить это, запустив:

$ docker image inspect debian:9 | jq '.[0].RootFS.Layers'
[
  "sha256:13d5529fd232cacdd8cd561148560e0bf5d65dbc1149faf0c68240985607c303"
]

...так что проигнорируем. Найдем второй слой:

# grep -l 41494b03ef195ce6db527bd68b89cbebdace66210b4c142e95f8553fcb0bf51e \
  /var/lib/docker/image/overlay2/layerdb/sha256/*/diff
/var/lib/docker/image/overlay2/layerdb/sha256/14347a192896a59fdf5c1a9ffcac2f93025433c66136d3531d7bbb3aec53efc7/diff

Внутри того же каталога, что и этот файл diff, мы найдем файл с именемcache-id:

# cat image/overlay2/layerdb/sha256/14347a192896a59fdf5c1a9ffcac2f93025433c66136d3531d7bbb3aec53efc7/cache-id
118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75

Что cache-idидентифицирует каталог, в который был извлечен слой; мы можем найти его под/var/lib/docker/overlay2/<id>:

# ls /var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75
diff/ link lower work/

Нас интересует содержимое каталога diff/:

# find /var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef6
21ccb70cf14fe672dc74ef75/diff/
/var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75/diff/
/var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75/diff/root
/var/lib/docker/overlay2/118b1e4a401873e1db8849c0821d0280b4cf9ef621ccb70cf14fe672dc74ef75/diff/root/file.txt

Вот оно!


Примечание. Все вышеперечисленное предполагает, что вы используете overlay2драйвер хранилища (, который в настоящее время используется по умолчанию на большинстве, если не на всех платформах ). Если вы используете другой драйвер, расположение на диске будет другим.

0
05.04.2021, 10:09
3 ответа
Каталог

— это всего лишь один из многих типов файлов. Другие типы включают символическую ссылку , fifo , устройство , обычный , сокет ...

В выводе ls -nпервый символ указывает на тип. dдля каталога, -для обычного , lдля символической ссылки , так что вы можете сделать:

LC_ALL=C ls -Aqn | LC_ALL=C grep  -c '^-' # regular files only
LC_ALL=C ls -Aqn | LC_ALL=C grep -vc '^d' # anything but directory

(удалите опцию -A, если вы не хотите считать скрытые файлы ).

Вы также можете выполнить проверку после разрешения символической ссылки ,

LC_ALL=C ls -LAqn | LC_ALL=C grep  -c '^-' # regular files or symlinks to regulars
LC_ALL=C ls -LAqn | LC_ALL=C grep -vc '^d' # anything but directory and symlinks to dirs.

В оболочке zshэто также можно сделать с помощью подстановки:

(){print $#} *(NDoN.)  # regular
(){print $#} *(NDoN^/) # non-directories

После разрешения символических ссылок (добавлен квалификатор -glob):

(){print $#} *(NDoN-.)  # regular
(){print $#} *(NDoN-^/) # non-directories

(удалите квалификатор D, если вы не хотите подсчитывать скрытые файлы ).

oN— это отключить сортировку списка файлов в качестве оптимизации, поскольку нам не важен порядок. Реализация GNU lsимеет для этого опцию -U.

В любом случае ваш ls | wc -lневерен, поскольку он подсчитывает количество символов новой строки, используемых lsдля разграничения имен файлов (, по одному на файл ), а также символы новой строки в именах. файла (он также опускает скрытые файлы ). Использование параметра -qпомогает обойти это, так как символы новой строки в именах файлов отображаются как ?.

3
28.04.2021, 22:54

Обычно я использую:

find. -maxdepth 1 -type f | wc -l

Остерегайтесь этого:

  • здесь также учитываются имена файлов, начинающиеся с.
  • рассматривает только обычные файлы (не FIFO, символические ссылки и т.д.)
1
28.04.2021, 22:54

Я пока не могу оставлять комментарии, но вот решение для bash -. Это не так лаконично, но может казаться чище без использования grep.

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

i=0
for f in *
do
[[ -f "$f" ]] && let "i++"
done
echo $i

Или объединены в один -вкладыш,i=0; for f in *; do [[ -f "$f" ]] && let "i++"; done; echo $i

0
28.04.2021, 22:54

Теги

Похожие вопросы