Коротко. Тег можно перевесить на другое содержимое, дайджест нельзя. Ставьте образы из своего зеркала и по дайджесту, файлы сверяйте по контрольным суммам, ID образа между серверами не сравнивайте.

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

Симптом

  • Контейнер с тем же тегом на двух серверах ведёт себя по-разному.
  • После пересоздания контейнера без смены тега меняется версия библиотеки или поведение.
  • Образ, который скачивался вчера, сегодня не скачивается: его удалили из публичного реестра.

Последний пункт не теория. В 2025 году Bitnami убрал свои образы из публичного каталога в архивный bitnamilegacy, а образы MinIO к осени 2026 года не скачиваются ни с Docker Hub, ни с quay.io. Установки, которые скачивали их напрямую, перестали собираться в один день.

Почему так

У образа в реестре три идентификатора, и их часто путают.

  • Тег (elasticsearch:8.19.23, nginx:1.27, latest) это изменяемая ссылка. Плавающие теги вроде 1.27 перевешивают с каждым исправлением, но и точный тег могут пересобрать с тем же номером.
  • Дайджест (sha256:8b17…) это хеш манифеста. Он вычисляется из содержимого и не может указывать на другое содержимое. Образ, скачанный по дайджесту, всегда один и тот же.
  • ID образа показывает docker images. Это локальный идентификатор, и он зависит от того, как Docker хранит образы. В классическом хранилище это хеш конфигурации образа, в хранилище containerd он совпадает с дайджестом. Сравнивать ID между серверами нельзя.

Ещё тонкость: у многоплатформенного образа два уровня. Дайджест индекса общий, внутри него у каждой платформы (amd64, arm64) свой манифест со своим дайджестом. Закреплять стоит дайджест индекса, тогда на любой платформе скачается то, что было опубликовано вместе.

Диагностика

Какой дайджест у скачанного образа:

docker inspect --format '{{index .RepoDigests 0}}' elasticsearch:8.19.23

Какой дайджест сейчас у тега в реестре и из каких платформ состоит образ, без скачивания:

docker buildx imagetools inspect elasticsearch:8.19.23

Если дайджест в реестре отличается от того, что стоит у вас, под тегом уже другое содержимое.

Для файлов, а не образов (дистрибутивы, архивы, бинарники), то же делают контрольные суммы: производитель публикует файл с суммами, вы сверяете перед установкой.

sha256sum -c SHA256SUMS --ignore-missing

Что сделать

  1. В конфигурации установки ссылаться на образ вместе с дайджестом: elasticsearch:8.19.23@sha256:8b17…. Тег остаётся для человека, дайджест решает, что скачается.
  2. Держать свой реестр-зеркало и ставить из него. Внешний реестр может удалить образ, ваше зеркало нет.
  3. При переносе образа в своё зеркало проверять, что дайджест не изменился. Перетегирование внутри реестра без перепаковки сохраняет дайджест, пересборка его меняет.
  4. Сверять контрольные суммы дистрибутивов до установки, а не после проблем.
  5. Записывать дайджесты установленных образов в журнал изменений: при разборе «что поменялось с прошлой недели» это первая строка.

Для Directum RX на Linux последние пункты особенно полезны: сервисы разворачиваются в контейнерах, и в справке вендора описана сборка своих базовых образов для компаний со строгими требованиями к безопасности. Такие образы стоит хранить в своём реестре и ссылаться на них по дайджесту.

Чего не делать

  • Не ставить latest на продуктивный контур. Через месяц никто не скажет, что именно там работает.
  • Не сравнивать ID образа между серверами. Он зависит от способа хранения образов в Docker.
  • Не рассчитывать, что публичный реестр будет всегда. Образы удаляют, переносят и закрывают.