Сегодня хочу поднять тему, которую редко обсуждают отдельно, но без неё Docker просто не работал бы так стабильно и предсказуемо - манифесты образов.
Периодически в разные частях документации или статьях про Docker вы будете встречать "манифесты". Обычно это звучит как что-то второстепенное: мол, есть какая-то мета-информация, по которой Docker собирает образ из слоёв.
Но на деле это одна из ключевых деталей, которая отвечает за то, что контейнеры:
воспроизводимы
одинаковые на разных машинах
и не превращаются в "ну у меня работало".
Я попытаюсь все описать максимально просто.
Docker Manifest - это JSON-документ, который описывает образ. Можно представить его как схему или инструкцию, по которой Docker понимает:
какие слои относятся к образу
какие контрольные суммы должны быть у каждого слоя
в каком порядке их нужно использовать
для какой ОС и архитектуры этот образ подходит
И важный момент: когда ты делаешь docker pull, Docker сначала получает манифест, а уже потом начинает скачивать слои.
Как посмотреть манифест самому: docker manifest inspect nginx:latest.

Тут можно заметить, что один тег (nginx:latest) может ссылаться сразу на несколько вариантов образа - например под amd64 и arm64. Это как раз история про multi-arch. Иногда под словом manifest имеют в виду не сам образ, а manifest list (index). Это как меню: Docker смотрит на твою платформу и выбирает подходящий вариант (amd64/arm64).
Каждый слой Docker-образа имеет SHA256-хеш, который вычисляется из его содержимого.
Логика максимально простая:
поменялся файл
поменялось содержимое
поменялся хеш
значит получился другой слой
По сути это очень похоже на философию Git: всё завязано на содержимое, а не на "имя файла".
Docker Registry использует Content Addressable Storage - то есть хранит и раздаёт данные не по названию, а по их хешам.
Что происходит при push / pull?
Если упростить до понятной схемы, то процесс примерно такой:
клиент сначала отправляет/получает манифест
registry проверяет хеши и наличие слоёв
передаются только те слои, которых ещё нет
каждый слой проверяется по SHA256
То есть никакой лишней передачи данных и никаких "примерно совпало".
Комбинация манифестов и хешей даёт сразу несколько сильных преимуществ:
Безопасность - слой нельзя незаметно подменить
Экономия места - одинаковые слои не хранятся по сто раз
Целостность - скачанное гарантированно равно загруженному
Версионирование - образ это конкретная комбинация слоёв, а не “что-то похожее”
Именно поэтому условный nginx:latest на dev и на prod - это реально один и тот же образ, а не "почти такой же, но чуть другой". Ладно, давайте будем более дотошными. На самом деле нет - использовать latest плохая практика. За время пока образ приехал,- там уже могут быть разные образы.
Как минимум используйте конкретный тег, а еще лучше даже sha256 docker pull nginx@sha256:...
_________________
Хватит читать DevOps-статьи от людей без продакшена. Я рассказываю про свой реальный опыт в своем Telegram-канале DevOps Brain 🧠 ↩
