Файлы, упомянутые в главе

  • werf.yaml

В этой главе мы настроим в нашем базовом приложении работу с зависимостями. Важно корректно вписать зависимости в стадии сборки, что позволит не тратить время на пересборку зависимостей тогда, когда зависимости не изменились.

Что за стадии?

werf подразумевает, что лучшей практикой будет разделить сборочный процесс на этапы, у каждого из которых есть свои четкие функции и назначение. Каждый такой этап соответствует промежуточному образу — подобно слоям в Docker. В werf такой этап называется стадией, и конечный образ в итоге состоит из набора собранных стадий. Все стадии хранятся в хранилище стадий, которое можно рассматривать как кэш сборки приложения, хотя по сути это скорее часть контекста сборки.

Стадии — это этапы сборочного процесса, кирпичи, из которых в итоге собирается конечный образ. Стадия собирается из группы сборочных инструкций, указанных в конфигурации. Причем группировка этих инструкций не случайна, имеет определенную логику и учитывает условия и правила сборки. С каждой стадией связан конкретный Docker-образ.

Подробнее о том, какие стадии для чего предполагаются, можно посмотреть здесь. Если вкратце, то werf предлагает использовать для стадий следующую стратегию:

  • использовать стадию beforeInstall для инсталляции системных пакетов;
  • install — для инсталляции системных зависимостей и зависимостей приложения;
  • beforeSetup — для настройки системных параметров и установки приложения;
  • setup — для настройки приложения.

Другие подробности о стадиях описаны в документации.

Одно из основных преимуществ использования стадий в том, что мы можем перезапускать сборку не с нуля, а только с той стадии, которая зависит от изменений в определенных файлах.

В Java, в частности в spring, в качестве менеджера зависимостей может использоваться maven, gradle. Мы будем, как и ранее использовать maven, но для gradle принципиальных отличий не будет. Пропишем его использование в файле werf.yaml и затем оптимизируем его использование.

Подключение менеджера зависимостей

Пропишем разрешение зависимостей в нужную стадию сборки в werf.yaml:

shell:
  beforeSetup:
    - mvn -B -f pom.xml package dependency:resolve
shell: beforeSetup: - mvn -B -f pom.xml package dependency:resolve

Однако, если оставить всё так — стадия не будет запускаться при изменении pom.xml и любого кода в src/. Подобная зависимость пользовательской стадии от изменений указывается с помощью параметра git.stageDependencies:

git:
- add: /
  to: /app
  stageDependencies:
    beforeSetup:
    - pom.xml
    setup:
    - src
git: - add: / to: /app stageDependencies: beforeSetup: - pom.xml setup: - src

Теперь при изменении файла pom.xml или любого из файлов в src/ стадия setup будет запущена заново.

Оптимизация сборки

Сборка занимает много времени, поэтому оптимизировать её — важная задача. Применим два приёма:

  • Уменьшим объём скачиваемых файлов благодаря улучшенному использованию кэша maven.
  • Усовершенствуем использование пользовательских стадий

Даже в пустом проекте сборщику нужно скачать приличное количество файлов. Скачивать эти файлы раз за разом выглядит нецелесообразным, поэтому разумно переиспользовать кэш в .m2/repository между сборками. С помощью директивы mount будем хранить кэш на раннере:

mount:
- from: build_dir
  to: /root/.m2/repository
mount: - from: build_dir to: /root/.m2/repository

Усовершенствуем использование пользовательских стадий: отделим resolve зависимостей от сборки jar — таким образом те коммиты, в которых правится исходный код, но не меняются зависимости, будут собираться быстрее.

shell:
  beforeSetup:
    - cd /app
    - mvn -B -f pom.xml dependency:resolve
  setup:
  - cd /app
  - mvn -B -f pom.xml package
shell: beforeSetup: - cd /app - mvn -B -f pom.xml dependency:resolve setup: - cd /app - mvn -B -f pom.xml package