Когда вы запускаете docker pull nginx, вы получаете не просто «образ nginx», а конкретный набор слоёв, зафиксированный криптографическими хешами. Именно эти хеши позволяют ответить на два практических вопроса: действительно ли образ, который работает в продакшене, совпадает с тем, что прошёл тестирование, и пришёл ли он из того источника, которому вы доверяете. Разберём, как устроены эти хеши, какие из них для чего нужны и как на их основе строить проверку происхождения.
- Зачем вообще нужны хеши образов
- Image ID, digest и тег: три разных идентификатора
- Тег
- Image ID (ID локального образа)
- Digest (дайджест)
- Как посмотреть хеши образа
- Проверка целостности: сверка digest между средами
- Проверка происхождения: что даёт и чего не даёт digest
- Доверенные реестры и приватные репозитории
- Подпись образов
- SBoM и provenance-аттестации
- Сканирование уязвимостей
- Типичные ошибки при работе с хешами
- Практический минимум для команды
- Частые вопросы
- Можно ли подделать digest образа?
- Образ скачан по тегу — как узнать его digest?
- Достаточно ли подписи образа для безопасности?
- Что делать, если digest изменился после пересборки из того же кода?
- Что запомнить
Зачем вообще нужны хеши образов
Контейнерный образ — это набор слоёв (файловых систем) плюс манифест с метаданными. Каждый слой и каждый манифест имеют собственный хеш по алгоритму SHA-256. Хеш здесь выполняет роль отпечатка: если изменится хотя бы один байт содержимого, хеш станет другим. Это даёт три гарантии:
- Неизменяемость. Образ с конкретным дайджестом невозможно «подменить тихо» — любое изменение содержимого даёт новый хеш.
- Воспроизводимость. Один и тот же дайджест означает один и тот же набор байтов на любой машине и в любом реестре.
- Проверяемость цепочки поставки. Сверяя хеши между сборкой, реестром и развёртыванием, вы убеждаетесь, что образ нигде не был заменён или повреждён.
Image ID, digest и тег: три разных идентификатора
Начинающие часто путают эти понятия, а от путаницы страдает вся логика проверки. Разница принципиальна.
Тег
Тег — это человекочитаемая метка вроде nginx:1.27-alpine. Он указывает на образ, но не гарантирует его неизменность: владелец репозитория может перевыпустить тот же тег с новым содержимым. Тег удобен для разработки, но непригоден как ссылка на проверенный артефакт.
Image ID (ID локального образа)
Это хеш конфигурации образа, который виден в выводе docker images. Он идентифицирует образ локально после загрузки, но не является универсальной ссылкой в реестре и зависит от формата манифеста. Для сверки между средами он подходит хуже, чем digest.
Digest (дайджест)
Дайджест — это хеш манифеста образа в формате repo@sha256:…. Именно он фиксирует точное содержимое: набор слоёв, платформу и метаданные. Дайджест одинаков независимо от того, откуда вы скачали образ, поэтому он и служит основой проверки происхождения и целостности.
| Идентификатор | Что фиксирует | Может измениться без вашего ведома | Где использовать |
|---|---|---|---|
| Тег | Метку репозитория | Да, при повторной публикации тега | Разработка, черновые сборки |
| Image ID | Локальную конфигурацию образа | Нет, но привязан к окружению | Локальная диагностика |
| Digest | Точный манифест и слои | Нет | Продакшен, CI/CD, аудит |
Как посмотреть хеши образа
Базовые команды доступны в любом стандартном окружении Docker:
- Список локальных образов с ID: docker images —digests — покажет и репозиторий, и тег, и digest, если он известен локально.
- Подробности одного образа: docker inspect <имя> — в секции RepoDigests перечислены дайджесты, под которыми образ был загружен.
- Манифест в реестре: docker manifest inspect repo/image:tag — покажет структуру манифеста и хеши слоёв до скачивания.
- Слои и история: docker history repo/image:tag — поможет понять, из каких шагов собран образ.
Точные флаги и формат вывода зависят от версии Docker и используемого движка контейнеров, поэтому при расхождениях сверяйтесь со справкой вашей версии командой —help.
Проверка целостности: сверка digest между средами
Самая простая и надёжная практика — закреплять в продакшене образы по дайджесту, а не по тегу. Типичный порядок действий выглядит так:
- В CI после сборки получите digest опубликованного образа и сохраните его как артефакт пайплайна.
- Прогоните тесты именно на этом образе, обращаясь к нему по digest.
- В манифестах развёртывания (например, в Kubernetes) укажите образ в виде репозиторий@sha256:….
- Перед выпуском убедитесь, что digest в манифесте совпадает с digest, который прошёл тестирование.
Так вы исключаете классическую ошибку, когда между тестированием и деплоем тег молча указал уже на другой образ. Если digest не совпал — образ либо пересобран, либо подменён, и в обоих случаях автоматизация должна остановить выпуск.
Проверка происхождения: что даёт и чего не даёт digest
Здесь важно понимать ограничение. Digest доказывает, что байты образа те же самые, но сам по себе не отвечает на вопрос, кто их создал и откуда они пришли. Подделать содержимое под чужой digest практически невозможно, однако злоумышленник может опубликовать вредоносный образ со своим честным digest в похожем репозитории (тайпсквоттинг) или подсунуть его через скомпрометированный CI. Поэтому проверка происхождения строится поверх хешей и включает несколько уровней.
Доверенные реестры и приватные репозитории
Первый уровень — организационный. Образы для продакшена публикуются только в контролируемый вами реестр, а рабочие нагрузки получают доступ исключительно к нему. Публичные базовые образы при этом импортируются: копируются в приватный репозиторий после проверки, и дальше все среды используют только вашу копию. Это устраняет зависимость от внешних реестров и риск тайпсквоттинга.
Подпись образов
Второй уровень — криптографическая подпись. Инструменты класса Sigstore Cosign позволяют подписать образ по его digest закрытым ключом или через прозрачный механизм подписи без долгоживущих ключей. Проверяющая сторона перед развёртыванием убеждается, что подпись соответствует ожидаемому отправителю и digest совпадает. В политике admission-контроллера Kubernetes можно запретить запуск любых неподписанных образов — тогда непроверенный артефакт физически не попадёт в кластер.
SBoM и provenance-аттестации
Третий уровень — метаданные о составе и происхождении. Спецификация SBoM (Software Bill of Materials) описывает, какие компоненты входят в образ, а аттестации provenance фиксируют, как и где образ был собран: какой билдер, какие исходники, какая инструкция сборки. Современные сборщики умеют генерировать такие аттестации автоматически; их можно подписывать вместе с образом и проверять той же цепочкой инструментов. Это закрывает вопрос не только «что внутри», но и «кем и как собрано».
Сканирование уязвимостей
Подпись подтверждает автора, но не безопасность содержимого. Поэтому отдельным шагом образы сканируются на известные уязвимости (инструменты вроде Trivy, Grype и аналогичных), а результат привязывается к digest. Политика может выглядеть так: в продакшен допускаются только подписанные образы без критических уязвимостей на момент сканирования.
Типичные ошибки при работе с хешами
- Использование тега latest в продакшене. Тег перемещается, и две развертки в разное время могут получить разные образы. Альтернатива — всегда фиксировать digest.
- Сверка image ID вместо digest. Локальный ID не всегда сопоставим между средами и форматами манифестов; канонический идентификатор для сверки — digest манифеста.
- Игнорирование мультиархитектурных манифестов. У образа может быть общий digest списка манифестов и отдельные digest для каждой архитектуры. При закреплении уточняйте, какой именно digest вы используете, чтобы на ARM-узлах не оказаться без подходящего варианта.
- Пересборка образа без обновления digest в манифестах. Даже пересборка из тех же исходников обычно даёт другой digest из-за меток времени и метаданных. Меняете образ — обновляйте ссылки везде.
- Доверие только подписи без проверки digest. Подпись должна быть привязана к конкретному digest; подписанный «вообще образ» без сверки хеша не защищает от подмены.
Практический минимум для команды
Если вы внедряете проверку происхождения с нуля, разумная последовательность такая:
- Запретите теги вида latest и плавающие теги в продакшен-манифестах; используйте digest.
- Настройте публикацию образов только в контролируемый реестр и ограничьте доступ рабочих нагрузок к нему.
- Внедрите подпись образов в CI и проверку подписи при развёртывании (admission-политики в Kubernetes или эквивалентные механизмы).
- Добавьте генерацию SBoM и provenance-аттестаций, подпишите их вместе с образом.
- Подключите сканирование уязвимостей с привязкой результата к digest и определите пороги блокировки выпуска.
- Зафиксируйте процедуру реагирования: что делать при несовпадении digest, отсутствии подписи или новых критических уязвимостях в уже развёрнутом образе.
Частые вопросы
Можно ли подделать digest образа?
Подобрать другой контент под существующий SHA-256 хеш на текущем уровне технологий практически нереально. Реальные риски лежат не в криптографии, а в организационных слабых местах: компрометация CI, публикация в похожий репозиторий, отсутствие проверки подписи при развёртывании.
Образ скачан по тегу — как узнать его digest?
После загрузки выполните docker inspect и посмотрите секцию RepoDigests, либо используйте docker images —digests. Полученное значение можно закрепить в манифестах для последующих развертываний.
Достаточно ли подписи образа для безопасности?
Нет. Подпись подтверждает авторство и целостность, но не отсутствие уязвимостей и не корректность конфигурации. Полноценная проверка сочетает подпись, сканирование, SBoM и ограничения на источники образов.
Что делать, если digest изменился после пересборки из того же кода?
Это нормальное поведение: метаданные сборки влияют на итоговый хеш. Обновите digest во всех манифестах и заново пройдите цикл проверки — подписания, сканирования и тестирования.
Что запомнить
Главный принцип: тег — для людей, digest — для машин и аудита. Закрепляйте продакшен-образы по дайджесту, публикуйте их только через контролируемый реестр и добавляйте поверх хешей проверку происхождения: подпись, SBoM, аттестации сборки и сканирование. Первым шагом достаточно провести ревизию текущих манифестов и заменить плавающие теги на конкретные digest — это самая дешёвая мера с самым заметным эффектом для воспроизводимости и безопасности поставки.
