Слои образа
Как образ собирается из слоёв и что происходит при записи.
Стек слоёв
┌──────────────────────────────────────┐
│ записываемый слой container'а │ ← исчезает с container'ом
├──────────────────────────────────────┤
│ COPY app/ ./app/ │ ┐
├──────────────────────────────────────┤ │
об- │ RUN pip install -r requirements.txt │ │ слои образа:
раз ├──────────────────────────────────────┤ │ неизменяемы,
│ COPY requirements.txt . │ │ адресуются
├──────────────────────────────────────┤ │ по содержимому
│ FROM python:3.13-slim │ ┘
└──────────────────────────────────────┘
│
▼
OverlayFS собирает их
в одно дерево: merged
Как читать
Верхние слои перекрывают нижние. Приложение видит одно дерево каталогов; то, что оно собрано из шести источников, снаружи не заметно.
Записываемый слой принадлежит container'у, а не образу: два container'а из одного образа имеют разные верхние слои и общие нижние.
Что здесь неочевидно
Copy-up: запись копирует файл целиком.
до записи: после записи одного байта:
верхний слой (пусто) верхний слой [файл 128 МиБ]
▲
нижний слой [файл 128 МиБ] нижний слой [файл 128 МиБ]
(остался нетронутым)
Один sed -i по файлу в 128 МиБ даёт записываемый слой в 128 МиБ. chmod тоже вызывает копирование: меняются метаданные, копируется файл.
Удаление не уменьшает образ.
RUN rm /секрет
│
▼
верхний слой: whiteout-запись «файла /секрет здесь нет»
нижний слой: сам файл, целиком, извлекается
Проверяется распаковкой:
docker save образ -o образ.tar
mkdir -p распакованное && tar -xf образ.tar -C распакованное
grep -rl 'секретная строка' распакованное/
Отсюда: секрет, скопированный и удалённый следующей инструкцией, находится в образе. Правильный способ — RUN --mount=type=secret.
Кэш сборки
Dockerfile состояние кэша при изменении app/main.py
──────────────────────────────────────────────────────────────
FROM python:3.13-slim CACHED
COPY requirements.txt CACHED ← файл не менялся
RUN pip install -r ... CACHED ← предыдущий слой тот же
COPY app/ ./app/ пересчёт ← содержимое изменилось
Если поменять порядок:
FROM python:3.13-slim CACHED
COPY . . пересчёт ← любое изменение любого файла
RUN pip install -r ... пересчёт ← предыдущий слой другой
Один недействительный слой обесценивает все последующие: слой — это состояние файловой системы после предыдущих, и при другом предыдущем результат может быть другим.
Три digest'а одного образа
index (список манифестов)
sha256:aaa… ← для многоплатформенных
│
┌───────────┼───────────┐
▼ ▼ ▼
manifest manifest manifest
linux/amd64 linux/arm64 …
sha256:bbb… ← этот в RepoDigests
│
├──► config sha256:ccc… ← этот показывает docker images
└──► слои sha256:ddd…, …
Для закрепления версии годится тот, что показывает RepoDigests:
docker image inspect образ --format '{{index .RepoDigests 0}}'
Где смотреть
| Что нужно | Команда |
|---|---|
| Слои и их размер | docker history образ --human |
| Полные команды | docker history образ --no-trunc |
| Что записал container | docker diff имя |
| Общий размер | docker image inspect образ --format '{{.Size}}' |
| Все слои | docker image inspect образ --format '{{json .RootFS.Layers}}' |
Подробнее
Урок 3.1. Устройство образа
Урок 3.2. Слои и copy-on-write
Урок 17.5. OverlayFS
Навигация
Раздел 03. Работа с Images
Диаграмма кэша сборки
Главное оглавление