Практика Docker: знакомимся с docker-maven-plugin
Олег Накрайников рассказал, как запускать внешние зависимости в Docker для интеграционных тестов в spring-boot-проекте.
 
 

Запускать интеграционные тесты можно по-разному, но в работе я ориентируюсь на следующие требования:
- способ должен позволять запускать тесты и локально, и на CI;
- развёртывание зависимостей не должно чрезмерно увеличивать время сборки;
- не должно возникать проблем с поиском сборок зависимостей (баз данных, брокеров и так далее).
Поэтому я использую maven — это фреймворк для автоматизации сборки проектов от Apache, в котором структура проекта описывается на подмножестве XML, языке POM. Далее расскажу, как запускать интеграционные тесты с его помощью, и поделюсь конфигурациями плагинов.
Как запустить интеграционный тест в maven
Интеграционные тесты в maven запускаются одной строкой:
mvn verify -Docker_host = localhostТеперь настроим maven. Если прописать свойство docker_host, то сборщик активирует профиль IT:
<profile>
    <id>it</id>
    <activation>
        <property>
            <name>docker_host</name>
        </property>
    </activation>Профиль включает плагины maven-failsafe-plugin и docker-maven-plugin.
Первый необходим для запуска самих тестов:
<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goals>
                <goal>verify</goals>
            </goals>
        </execution>
    </executions>А второй — как раз для запуска зависимостей в контейнерах Docker:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.38.0</version>В конфигурации docker-maven-plugin необходимо указать образы нужных нам зависимостей:
<configuration>
  <dockerHost>tcp://${docker_host}:${docker_port}</dockerHost>
  <images>
    <image>
      <name>postgres:11</name>
      <alias>postgresql</alias>
      <run>
        <env>
          <POSTGRES_USER>postgres</POSTGRES_USER>
          <POSTGRES_PASSWORD>postgres</POSTGRES_PASSWORD>
          <POSTGRES_DB>postgres</POSTGRES_DB>
        </env>
        <ports>
          <port>${postgres_port}:5432</port>
        </ports>
        <wait>
          <log>(?s)database system is ready to accept connections.*database system is ready to accept connections</log>
          <time>10000</time>
        </wait>
      </run>
    </image>
  </images>
</configuration>Также укажем, что перед проведением тестов контейнеры нужно собрать и запустить, а по завершении — остановить и удалить:
<executions>
  <execution>
    <id>start</id>
    <phase>pre-integration-test</phase>
    <goals>
      <goal>build</goals>
      <goal>start</goals>
    </goals>
  </execution>
  <execution>
    <id>stop</id>
    <phase>post-integration-test</phase>
    <goals>
      <goal>stop</goals>
    </goals>
  </execution>
<executions>Зачем нужно свойство docker_host
<configuration>
  <dockerHost>tcp://${docker_host}:${docker_port}</dockerHost>
  <images>
    <image>В docker_host указывается адрес, по которому расположен docker engine — на нём плагин и будет работать с контейнерами. Данное свойство позволит запускать интеграционные тесты как локально на машине разработчика, так и на CI.
Статья написана на основе треда Олега в Twitter.
Всё чаще в современных CI воркеры разворачиваются в виде docker-контейнеров. Поэтому для сборки нашего проекта необходимо развернуть два контейнера: maven и Docker in Docker (dind). В maven собирается проект и запускаются интеграционные тесты, а в dind — контейнеры с зависимостями. Адрес dind-контейнера как раз указывается в свойстве docker_host.
Что сделать, чтобы тесты добрались до зависимостей?
Через плагин maven-failsafe-plugin устанавливаем переменные окружения и прописываем настройки в application.yml:
<configuration>
  <environmentVariables>
    <spring.profiles.active>tests-remote</spring.profiles.active>
    <postgres_host>${docker_host}</postgres_host>
    <postgres_port>${docker_por}</postgres_port>
  </environmentVariables>
</configuration>spring:
  profiles: 
    active: tests-local
external.url: http://localhost:8001
db:
  username: 'postgres'
  password: 'postgres'
  driverClassName: 'org.postgresql.Driver'
  minimumIdle: 5
  maximumPoolSize: 10
  connectionTimeout: 10000
  validationTimeout: 5000
  connectionsTestQuery: 'SELECT 1'
___
spring: 
  config:
    activate: 
      on-profile: tests-local
db:
  jdbcUrl: 'jdbc:postgresql://localhost:5432/postgres'
___
spring:
  config:
    activate:
      on-profile: test-remote
db:
  jdbc:postgresql://${postgres.host}:${postgres.port}/postgres'Здесь on-profile: tests-local нужен для запуска тестов из IDE, а on-profile: tests-remote — через maven.
Чтобы писать и запускать тесты из IDE, придётся поднять зависимости вручную двумя командами:
mvn docker:start -Docker_host=localhost
mvn docker:stop -Docker_host=localhostИзложенный подход обладает следующими преимуществами:
- Вы сможете запускать тесты и локально, и на CI.
- Контейнеры будут создаваться только перед тестами и удаляться сразу после их окончания.
- Через docker-maven-plugin можно строить достаточно сложное окружение с множеством контейнеров и сетью между ними.
Пример проекта, собранного с помощью docker-maven-plugin, можно посмотреть в моём GitHub-репозитории, а почитать документацию к плагину — здесь.
 Все
                                Все
                             Истории
                                        Истории Дизайн
                                    Дизайн Код
                                    Код Геймдев
                                    Геймдев Бизнес
                                    Бизнес Маркетинг
                                    Маркетинг Управление
                                    Управление Кино
                                    Кино Музыка
                                    Музыка Проектная фотография
                                    Проектная фотография Развитие
                                    Развитие Здоровье
                                    Здоровье Деньги
                                    Деньги Образование
                                    Образование EdTech
                                    EdTech Корп. обучение
                                    Корп. обучение Блог Skillbox
                                    Блог Skillbox Глоссарий
                                        Глоссарий Спецпроекты
                                        Спецпроекты Профориентация
                                        Профориентация 
                                     
                     
                     
                                     
                                     
                                     
                                    