🌌 Цифровий відбиток фундаменту — С.І.Д. не любить сюрпризів від «ТехНови»: варто їм підмінити фундамент його міста — базовий образ — під тим самим іменем, і привид уже не привид. Розберися разом із ним, як зафіксувати точний цифровий відбиток (digest) довіреної збірки замість мінливого людяного тега.
Людяний тег на кшталт ubuntu:24.04 або myapp:latest технічно є не ідентифікатором
вмісту, а мутабельним посиланням у реєстрі (registry) — записом у таблиці «ім'я → digest»,
який власник репозиторію (чи будь-хто з правами push) може будь-коли перезаписати на
інший вміст під тим самим іменем. Це зручно для розробки (latest завжди вказує на
щось нове), але небезпечно для відтворюваності й довіри: два docker pull ubuntu:24.04
у різний час можуть повернути різні байти, і жодним чином це не видно з самого тега.
Digest, навпаки, — це криптографічний хеш (SHA-256) маніфесту образу: структури,
що описує список шарів та їхні власні digest-и. Формат посилання —
образ@sha256:<64 hex-символи>. Оскільки SHA-256 практично неможливо підібрати
колізію, digest однозначно й незмінно прив'язаний до конкретного бінарного вмісту:
docker pull ubuntu@sha256:abcd... завжди поверне побайтово ідентичний результат,
незалежно від того, коли й де ця команда виконується, — навіть якщо власник
репозиторію тим часом перепризначив тег 24.04 на щось інше.
Це має пряме відношення до content trust: коли конвеєр CI/CD чи продакшн-скрипт
посилається на образ за тегом, він фактично довіряє реєстру не підміняти вміст
непомітно — а це і є вектор атаки типу «tag mutation» чи компрометації облікового
запису в реєстрі. Посилання за digest усуває цю довіру як залежність: навіть якщо
зловмисник отримає доступ до реєстру й перезапише тег на шкідливий образ, вже
зафіксований у скрипті digest продовжить резолвитись у старий, довірений вміст (або
ж docker pull за digest, якого більше немає в реєстрі, просто впаде з помилкою —
що теж краще за тиху підміну).
Практична рекомендація — «pinning»: у продакшн-Dockerfile та CI-конфігураціях
фіксувати базові образи саме за digest, отриманим одноразово й перевіреним
(наприклад, FROM ubuntu@sha256:2e8...), а не за мінливим тегом. Це не заважає
оновлюватися свідомо: коли потрібна нова версія, digest у конфігурації змінюють
явним коммітом, що проходить рев'ю, — на відміну від тега, зміна вмісту за яким
відбувається «десь у реєстрі» без жодного сліду в репозиторії коду.
Окремо варто розрізняти digest конкретного образу для однієї архітектури і
manifest list (multi-arch index) — той самий тег може резолвитись у різні digest-и
залежно від архітектури (amd64 проти arm64); docker inspect --format '{{.RepoDigests}}' покаже, який саме digest фактично був витягнутий на цій машині,
що корисно для аудиту вже наявних образів.
Прочитати Docker docs «Image digests» і розділ про Content Trust/Notation; порівняти docker pull ubuntu:24.04 з docker pull ubuntu@sha256:
Чому тег latest (чи будь-який інший людяний тег) не гарантує відтворюваності збірки, а digest (sha256:...) — гарантує?
sha256:c1d3101…. Імовірність такого — один до кількох мільярдів, тож або творці перебирали збірки до ранку, або на клавіатурі знову спав Пиксель. Так чи інак: довіряй відбитку, а не імені — як довіряєш голосу зі 101.9, а не назві станції.Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.
docker pulldockerdocker <підкоманда> --help — довідка).docker inspect-f '{{.State.Pid}}' — витягнути одне поле.💡 Прочитати README прямо в терміналі: cat README.md (виведе весь файл) або less README.md (посторінково; вихід — клавіша q).
Довідка з будь-якої команди: man curl (повний посібник, вихід — q) або коротко curl --help; для підкоманд — docker run --help, cargo build --help.