Кеш и артефакты в пайплайне
Чем кеш отличается от артефакта, как кешировать зависимости и слои образа и как передавать результат между job.
Две похожие, но разные вещи
В пайплайне есть два механизма сохранить файлы между запусками: кеш и артефакт. Их легко спутать, а нужны они для разного.
- Кеш ускоряет: сохраняет то, что дорого создавать заново (зависимости, скачанные пакеты), чтобы не качать каждый раз. Если кеш пропал, пайплайн просто отработает медленнее.
- Артефакт передаёт результат: файлы, которые произвёл один job и которые нужны следующему (собранный бинарь, отчёт о тестах). Если артефакт пропал, следующий job сломается.
Простое правило: кеш для скорости, артефакт для передачи результата.
Кеш зависимостей
Каждый job стартует в чистом окружении и заново тянет зависимости. На большом проекте это минуты. Кеш сохраняет папку зависимостей и переиспользует её:
test:
cache:
key:
files:
- package-lock.json # кеш обновится только при смене зависимостей
paths:
- .npm/
script:
- npm ci --cache .npm --prefer-offline
- npm test
Обрати внимание, что кешируется .npm/, а не node_modules/. Кешировать
node_modules вместе с npm ci бессмысленно: npm ci первым делом
удаляет каталог целиком и ставит всё заново из lock-файла. Кеш
восстановится, тут же будет снесён, и в конце job GitLab запакует его
обратно. Только потеря времени.
Экономия живёт на уровне npm-store. Флаг --cache .npm кладёт
скачанные тарболлы в каталог проекта, --prefer-offline заставляет npm
брать их оттуда вместо сети. Установка всё равно происходит, но без
скачивания.
Ключ кеша тоже важен. key: $CI_COMMIT_REF_SLUG даёт свой кеш на
каждую ветку, но обновляется он на каждом запуске. Привязка к хешу
lock-файла точнее: кеш меняется ровно тогда, когда меняются
зависимости.
Кеш слоёв образа
Docker-сборка тоже кешируется по слоям из прошлого урока про образы. Но в CI каждый job стартует на чистом раннере, где локального кеша слоёв нет вообще.
Классический совет docker build --cache-from registry/app:latest
здесь работает плохо: образа нет в локальном хранилище, а сам по себе
--cache-from его не скачивает. Формально команда отрабатывает, по
факту процент попаданий нулевой.
Рабочий вариант — buildx с кешем, который живёт в registry:
docker buildx build \
--cache-from type=registry,ref=$CI_REGISTRY_IMAGE:cache \
--cache-to type=registry,ref=$CI_REGISTRY_IMAGE:cache,mode=max \
-t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA --push .
--cache-from тянет кеш из реестра сам, --cache-to заливает
обновлённый обратно. mode=max сохраняет слои всех стадий, включая
промежуточные из multi-stage — без него в кеш попадёт только финальный
образ, и вся тяжёлая стадия сборки будет пересчитываться каждый раз.
Артефакты между job
Job собрал бинарь, а деплой-job должен его взять. Чистое окружение не делится файлами само, поэтому результат объявляют артефактом:
build:
stage: build
script:
- go build -o app
artifacts:
paths:
- app
expire_in: 1 week
deploy:
stage: deploy
script:
- ./app --version # артефакт из build уже здесь
GitLab сохранит app после build и распакует в deploy. expire_in
ограничивает срок хранения, чтобы артефакты не копились вечно.
Отдельный частый случай — артефакты-отчёты: junit-результаты тестов, coverage. Их собирают, чтобы показать в UI пайплайна, даже если дальше они не нужны.
Что важно запомнить
Кеш ускоряет сборку и переживает потерю без поломки; артефакт передаёт результат между job, и его потеря ломает следующий шаг.
Кеш зависимостей привязывают к lock-файлу, чтобы он обновлялся только при
смене зависимостей. Кешируют npm-store (.npm/), а не node_modules/:
npm ci всё равно сносит каталог перед установкой.
Слои образа в CI кешируют через docker buildx с
--cache-from/--cache-to type=registry и mode=max. Голый
docker build --cache-from на чистом раннере не даёт попаданий.
Артефакты объявляют через artifacts: paths, ограничивают expire_in и
используют ещё и для отчётов тестов в UI.
В следующем уроке разберём безопасность в пайплайне: проверки на уязвимости и секреты.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс