CLOVER🍀

That was when it all began.

docker-maven-pluginで、Integration Test時にDockerコンテナの起動/停止をする

Docker+Mavenで、テスト時にDockerコンテナを起動してテストして…みたいなことを、そういえばやったことが
ないなぁと思いまして。

いつも、わりかしふつうにdocker runしてます。

で、MavenでDockerを使うプラグインの情報をなんか見たことがあったので、軽く調べて試してみました。

今回は、docker-maven-pluginを使います。

https://github.com/fabric8io/docker-maven-plugin

ドキュメントはこちら。

docker-maven-plugin/intro.md at master · fabric8io/docker-maven-plugin · GitHub

docker-maven-plugin

docker-maven-pluginを使用するには、Mavenが使えることというのはさることながら、Dockerが
インストールされている、もしくはDocker APIが使えるホストにアクセスできる必要があるという
感じのようです。

このプラグインでできそうなこととして、docker build、run、stop、removeなど、Dockerのコマンドを使った
相応のこと(あと、Docker Composeまで)いろいろできそうですが、ビルドとかはふつうにdocker buildで
いいかなぁと思っているので、今回はrunとstopにフォーカスしてみました。

Docker Compose)
Docker Compose

では、試してみましょう。

お題

今回は、RedisのDockerイメージを使って、Integration Test時にRedisを起動、終了時にコンテナを停止する
といった使い方をしてみます。

RedisのDockerイメージは、こちら。

redis

あとは、テスト中にJedisを使ってRedisへアクセスしてみましょう、と。

準備

Integration Testで使うというのと、そもそもdocker-maven-pluginだという話なので、まずはMavenの
プラグイン設定から書いていきます。

        <plugins>
            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.20.0</version>
                <configuration>
                    <images>
                        <image>
                            <alias>redis-server</alias>
                            <name>redis:3.2.8</name>
                            <run>
                                <!-- docker:start -->
                                <namingStrategy>alias</namingStrategy>
                                <ports>6379:6379</ports>
                            </run>
                        </image>
                    </images>

                    <!-- docker:stop -->
                    <keepContainer>false</keepContainer>
                </configuration>
                <executions>
                    <execution>
                        <id>start</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>stop</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.19.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

maven-failsafe-pluginはまあいいとして、docker-maven-pluginについては利用するDockerイメージの設定や
runコマンドで指定するオプションなどを書いていきます。こちらは、またあとで。

Maven Failsafe Plugin – Introduction

依存ライブラリとしては、Jedis、JUnit、AssertJを用意。

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.6.2</version>
            <scope>test</scope>
        </dependency>

テストコードの準備と確認

動作確認に使用したテストコードは、こちら。Integration Testなので、テストクラス名は「〜IT」
としています。
src/test/java/org/littlewings/docker/DockerMavenPluginIT.java

package org.littlewings.docker;

import java.util.concurrent.TimeUnit;

import org.junit.Test;
import redis.clients.jedis.Jedis;

import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

public class DockerMavenPluginIT {
    @Test
    public void jedisGettingStarted() {
        Jedis jedis = new Jedis("localhost");

        assertThat(jedis.get("key"))
                .isNull();

        jedis.set("key", "value");
        assertThat(jedis.get("key"))
                .isEqualTo("value");
    }
}

確認は、「mvn verify」で。

$ mvn verify

実行すると、pre-integration-testでRedisを起動し、post-integration-testでRedisを停止してくれます。

[INFO] --- docker-maven-plugin:0.20.0:start (start) @ docker-maven-plugin-example ---
[INFO] DOCKER> [redis:3.2.8] "redis-server": Start container fec538d2c43e
[INFO] 
[INFO] --- maven-failsafe-plugin:2.19.1:integration-test (default) @ docker-maven-plugin-example ---

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.littlewings.docker.DockerMavenPluginIT
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.162 sec - in org.littlewings.docker.DockerMavenPluginIT

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- docker-maven-plugin:0.20.0:stop (stop) @ docker-maven-plugin-example ---
[INFO] DOCKER> [redis:3.2.8] "redis-server": Stop and removed container fec538d2c43e after 0 ms

この部分ですね。

[INFO] DOCKER> [redis:3.2.8] "redis-server": Start container fec538d2c43e

[INFO] DOCKER> [redis:3.2.8] "redis-server": Stop and removed container fec538d2c43e after 0 ms

OKそうですね。

docker-maven-pluginについて

で、docker-maven-plugin自体については、さらっと流してしまいました。そのあたりを見ていきましょう。

今回利用したのは、docker:startとdocker:stopです。

docker:start

docker:stop

設定としては、ごった煮で書いている感じもしますが、それぞれ見ていきましょう。今回書いた設定を再度書くと、こちらです。

            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.20.0</version>
                <configuration>
                    <images>
                        <image>
                            <alias>redis-server</alias>
                            <name>redis:3.2.8</name>
                            <run>
                                <!-- docker:start -->
                                <namingStrategy>alias</namingStrategy>
                                <ports>6379:6379</ports>
                            </run>
                        </image>
                    </images>

                    <!-- docker:stop -->
                    <keepContainer>false</keepContainer>
                </configuration>
                <executions>
                    <execution>
                        <id>start</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>stop</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

共通的な話としては、イメージ自体の記述はこんな感じで書くみたいですよ。Dockerイメージを複数書いても
いいみたいです。

                <configuration>
                    <images>
                        <image>
                            <name>[利用するDockerイメージ]</name>
                            <run>
                                <!-- 設定 -->
                            </run>
                            <!-- 設定 -->
                        </image>

                        <image>
                            ...
                        </image>
                    </images>
                </configuration>

どのような設定が可能かは、各種ゴールを見ていくことになります。

docker:start

docker:startゴールは、pre-integration-testフェーズで実行するように設定して、このタイミングでコンテナを
起動させています。

                    <execution>
                        <id>start</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>

コンテナに対する設定自体は、こちらを見て書いていきます。

Configuration

今回は、ports(-p相当)と、コンテナ名を設定しておきました。こちらと

                                <ports>6379:6379</ports>

aliasとnamingStrategyですね。

                           <alias>redis-server</alias>
                            <name>redis:3.2.8</name>
                            <run>
                                <!-- docker:start -->
                                <namingStrategy>alias</namingStrategy>

多くの設定は、runタグ内に書くことになります。詳細は、ドキュメントを…。

docker:stop

docker:stopは、あまり設定がありません。まずは、post-integration-test時にコンテナを停止するように設定。

                    <execution>
                        <id>stop</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>

設定は、今回keepContainer(stop時に、コンテナを削除するか)を指定して、stop時にコンテナを削除するように
しています…が、デフォルトがfalseなので、実は書かなくても意味は同じだったりします。

                    <!-- docker:stop -->
                    <keepContainer>false</keepContainer>

まあ、configurationタグ配下に書いて設定する、ということで。

設定をどこに書くかにちょっと悩んだりするのですが、ひとつ場所がわかればあとはドキュメント上での同じ並びの
項目は同じような場所に書いていくことになるので、そう困らないと思います。

まとめ

MavenでDockerを使う、docker-maven-pluginを試してみました。

設定の書き方でちょっと迷ったりしましたが、慣れれば使うのはそう難しくなさそうな気がします。

使えるところでは試していってみましょう。