Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Артефакты сборки: хранение и версионирование

Артефакты сборки: один артефакт на все окружения

Артефакты сборки: реестры образов и пакетов, версионирование по коммиту, неизменяемость, хранение и срок жизни.

Прямой ответ

Артефакт сборки — готовый к развёртыванию результат: Docker-образ, wheel-пакет, исполняемый файл, статический бандл. Главное правило: артефакт собирается один раз и продвигается по окружениям без пересборки. Если для тестового и продакшен-окружения выполняются разные сборки, проверенный код и работающий код — не одно и то же.

Типы хранилищ:

Артефакт Хранилище
Docker-образ Реестр образов: Docker Hub, GHCR, Harbor, Nexus
Python-пакет Индекс пакетов: PyPI, приватный devpi или Nexus
Бинарник, архив Хранилище артефактов CI, объектное хранилище
Helm-чарт Реестр чартов или OCI-реестр

Версионирование — ключевая часть. Варианты меток и их свойства:

Метка Свойства
latest Изменяемая, не указывает на конкретную версию; непригодна для выкатки
v1.4.2 Человекочитаемая, но требует дисциплины версионирования
Идентификатор коммита Однозначно связывает артефакт с кодом
Дайджест (sha256:...) Неизменяемый, криптографически проверяемый

Практика: тег для людей, дайджест для машин. Развёртывание по дайджесту исключает ситуацию, когда тег перезаписан и в окружение попала другая сборка.

# сборка с двумя метками и получение дайджеста
docker build -t registry.example.test/billing:1.4.2 \
             -t registry.example.test/billing:$(git rev-parse --short HEAD) .
docker push --all-tags registry.example.test/billing
docker inspect --format '{{index .RepoDigests 0}}' registry.example.test/billing:1.4.2

Неизменяемость важна: если тег можно перезаписать, невозможно утверждать, что развёрнутая версия совпадает с проверенной. В реестрах настраивают запрет перезаписи существующих тегов и хранение по дайджесту.

Практика: организация хранения и продвижения

1. Один артефакт на все окружения. Различия между окружениями задаются конфигурацией, а не содержимым артефакта. Если для продакшена нужна отдельная сборка, различие следует вынести во внешние параметры.

2. Связь артефакта с ревизией кода. По артефакту должно быть возможно определить коммит, из которого он собран. Практика — метка с идентификатором коммита и запись в метаданных образа.

3. Срок хранения и очистка. Реестр без политики очистки растёт неограниченно. Правило: хранить все версии последних N релизов, промежуточные сборки — ограниченное время, артефакты веток — до слияния.

# политика хранения (пример для реестра образов)
retention:
  keep_tags_matching: ["v*"]          # релизы — бессрочно
  keep_last_n_per_repo: 30            # промежуточные сборки
  delete_untagged_after_days: 14

4. Скан безопасности перед продвижением. Проверка зависимостей в образе выполняется один раз при сборке, а результат привязывается к дайджесту. О практике аудита зависимостей — в статье про аудит зависимостей.

5. Продвижение, а не повторение. Переход из тестового окружения в продакшен — это изменение ссылки на уже существующий артефакт. Такой подход делает откат быстрым: переключение на предыдущий дайджест вместо пересборки.

6. Размер артефакта влияет на скорость выкатки. Многослойный образ с историей сборки тянет лишние данные; многоэтапная сборка уменьшает размер — см. оптимизацию Docker-образов.

Рекомендации:

  1. Запретите перезапись тегов для релизов. Изменяемая метка делает невозможным воспроизведение развёртывания.
  2. Храните метаданные вместе с артефактом. Коммит, время сборки, версия базового образа, результат проверок — по ним восстанавливается контекст.
  3. Не храните секреты в артефакте. Ключи и пароли, попавшие в слой образа, извлекаются из любого скачанного артефакта.
  4. Свяжите артефакт с пайплайном. Артефакт, собранный вручную, не имеет ни проверок, ни связи с ревизией; такие сборки стоит запретить — о пайплайне в статье про CI/CD.
  5. Версионируйте по принятой схеме. Семантическое версионирование помогает понять характер изменения; детали — в статье про версии и релизы.

Практический сценарий: откат занял сорок минут вместо минуты

Контекст: после неудачной выкатки потребовался возврат к предыдущей версии. Процесс занял сорок минут и потребовал участия трёх человек.

  1. Что происходило. Откат выполнялся пересборкой образа из тега предыдущего релиза. За прошедшие две недели базовый образ обновился, поэтому пересборка дала другой набор системных библиотек и потребовала повторного прогона тестов.
  2. Причина 1. Развёртывание шло по тегу, а не по дайджесту, поэтому невозможно было точно указать прежнюю сборку.
  3. Причина 2. Политики хранения не было: старые образы удалялись автоматически, и нужный пришлось восстанавливать из резервной копии реестра.
  4. Действия. (а) Перешли на развёртывание по дайджесту; (б) релизные образы помечали неизменяемыми тегами и исключили из автоматической очистки; (в) откат реализовали как переключение ссылки на предыдущий дайджест; (г) добавили проверку, что выкатываемый дайджест соответствует прошедшему проверки.
  5. Результат. Следующий откат занял около минуты и выполнялся одним человеком; повторный прогон тестов не потребовался, потому что артефакт уже был проверен.

Вывод: скорость отката определяется не качеством пайплайна, а тем, сохраняется ли проверенный артефакт в неизменном виде. Хранение и версионирование артефактов — это страховка, стоимость которой заметна только в момент инцидента.

FAQ

Чем артефакт отличается от исходного кода? Артефакт — собранный результат, готовый к запуску. Код определяет, что должно получиться, но две сборки из одного кода могут отличаться из-за версий зависимостей и базовых образов. Поэтому развёртывают артефакт, а не код.

Нужно ли хранить все сборки? Релизные версии — да, в течение срока, необходимого для воспроизведения и отката. Промежуточные сборки веток хранят ограниченное время: их ценность заканчивается после слияния.

Можно ли использовать latest в продакшене? Нет. Тег latest указывает на последнюю отправленную сборку и может измениться в любой момент, поэтому поведение развёртывания становится непредсказуемым. Для автомата нужен дайджест или неизменяемый тег.

Где хранить артефакты фронтенда? В том же реестре или объектном хранилище с версионированием по коммиту. Ключевое требование то же: выкладываемый бандл должен быть тем же файлом, который прошёл проверки, а не пересобираться на этапе публикации.

Источники: Docker Registry docs, Python Packaging User Guide, GitHub Actions docs (artifacts) — ссылки в шапке.