MavenからDockerを起動する

#想定するユースケース
アプリケーションサーバの機能にすごく依存したプログラムを、サーバにデプロイする前にテストすることはとても困難です。変なモックをたくさん作るより、単体テストフェーズでも最初からデプロイしてしまってからテストしたい場合は多々あると思います。今はDockerを使えば、テスト用のサーバインスタンスを立てることは比較的容易にできます。そこで、Dockerコンテナを起動、ビルドしたものをデプロイした後、JUnitテストを実行するまでをMavenでやってみましょう。

この記事では、Dockerコンテナの起動・停止について書きます。

#Maven Dockerプラグインのセットアップ
MavenのDockerプラグインはいくつかあるようですが、今回やりたいのはDockerイメージのビルドではなく、コンテナの実行なので、コンテナ実行機能がある[fabric8io/docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin)を使ってみます。

##Docker Remote APIの有効化
DockerをAPIでリモートから操作できるようにするために、まずDocker Remote APIを有効化します。今回使用するDockerホストはFedoraですので、以下のファイルを編集してDockerの起動オプションに-H tcp://0.0.0.0:2375を追加します。

```text:/etc/sysconfig/docker
OPTIONS='--log-driver=journald -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock'
```

デフォルト設定であるUnixドメインソケット(-H unix:///var/run/docker.sock)の追加もお忘れなく。これを忘れると、ローカルで接続できなくなります。

##プラグインの有効化
ここからはMavenのpom.xmlの設定です。Intergration-testフェーズの前後で起動・停止を行うようにGoalの設定を行います。

```text:pom.xml
	<build>
		<plugins>
			<plugin>
				<groupId>io.fabric8</groupId>
				<artifactId>docker-maven-plugin</artifactId>
				<version>0.15.16</version>
				<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>
				<configuration>
				(後述)
				</configuration>
			</plugin>
		</plugins>
	</build>
```

##Docker環境の設定

```text:pom.xml
				<configuration>
					<dockerHost>http://192.168.56.11:2375</dockerHost>
					(後述)
				</configuration>	
```

##起動するコンテナのイメージの設定
コマンドラインでは以下のように実行する２つ（DBとAP）のイメージの設定をしてみます。

```text
$ docker run -d -h oracle11g -p 1521:1521 --dns=127.0.0.1 --name oracle11g oracle11g:ppm932.0003
$ docker run -d -h ppm93 -p 8080:8080 -p 1099:1099 --link oracle11g:oracle --name ppm93 ppm93:ppm932.0003 /bin/sh -c /root/ppm.sh
```

```text:pom.xml
				<configuration>
					(前述)
					<images>
						<image>
							<name>oracle11g:ppm932.0003</name>
							<alias>oracle11g</alias>
							<run>
								<hostname>oracle11g</hostname>
								<ports>
									<port>1521:1521</port>
								</ports>
								<dns>
									<host>127.0.0.1</host>
								</dns>
								<wait>
									<kill>60000</kill>
								</wait>
							</run>
						</image>
						<image>
							<name>ppm93:ppm932.0003</name>
							<alias>ppm93</alias>
							<run>
								<hostname>ppm93</hostname>
								<ports>
									<port>8080:8080</port>
									<port>1099:1099</port>
								</ports>
								<links>
									<link>oracle11g:oracle</link>
								</links>
								<cmd>/bin/sh -c /root/ppm.sh</cmd>
								<wait>
									<http>
										<url>http://ppm93:8080/</url>
									</http>
									<time>120000</time>
									<kill>60000</kill>
								</wait>
							</run>
						</image>
					</images>
				</configuration>	
```

waitは元のコマンドラインにはない要素でこのプラグイン独自のものですが、コンテナを起動後、指定したURLにアクセスできるようになるまで最大\<time\>ミリ秒待つ、というとても便利な機能です。この後テストを行う場合に、アプリケーションの起動が完了した状態で実施することができます。また、\<kill\>の方はコンテナ停止時のタイムアウトミリ秒です（docker stop -t 60と同等）。

#起動・停止の実行
EclipseからのMaven実行時に、post-integration-testフェーズを指定して実行します。

```text
[INFO] ------------------------------------------------------------------------
[INFO] Building server 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> docker-maven-plugin:0.15.16:start (default-cli) > initialize @ server >>>
[INFO] 
[INFO] <<< docker-maven-plugin:0.15.16:start (default-cli) < initialize @ server <<<
[INFO] 
[INFO] --- docker-maven-plugin:0.15.16:start (default-cli) @ server ---
[INFO] DOCKER> [oracle11g:ppm932.0003] "oracle11g": Start container 0e4da56d09c8
[INFO] DOCKER> [ppm93:ppm932.0003] "ppm93": Start container 706b2e5465a4
[INFO] DOCKER> [ppm93:ppm932.0003] "ppm93": Waiting on url http://ppm93:8080/ with method GET for status 200..399.
[INFO] DOCKER> [ppm93:ppm932.0003] "ppm93": Waited on url http://ppm93:8080/ 62382 ms[INFO] 
[INFO] >>> docker-maven-plugin:0.15.16:stop (default-cli) > initialize @ server >>>
[INFO] 
[INFO] <<< docker-maven-plugin:0.15.16:stop (default-cli) < initialize @ server <<<
[INFO] 
[INFO] --- docker-maven-plugin:0.15.16:stop (default-cli) @ server ---
[INFO] DOCKER> [ppm93:ppm932.0003] "ppm93": Stop and removed container adca51297b0b after 36947 ms
[INFO] DOCKER> [oracle11g:ppm932.0003] "oracle11g": Stop and removed container 3d5f19599c9f after 12220 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
```

起動は定義した順序、停止はその逆で実行してくれています。APコンテナ起動時に指定したURLにアクセスできるまで60秒ほど、AP、DBコンテナ停止時にもちゃんと停止し終わるまで待って終了していることがわかります。