Bambooとdocker-composeの連携について

このエントリーは、Atlassian Advent Calendar 2015 - Qiitaの7日目のエントリーです。

docker-composeによるCI環境上でのコンテナー間の連携

昨日のAtlassian Community Day 2015 | Peatixで、弊社グロースエクスパートナーズより、「Atlassian Summit 2015でのDevOps関連の取り組みについて」というテーマで講演致しましたが、その中で取り上げたdocker-composeの連携のデモについてこのエントリーでは紹介します。

CI界隈では「ポータブルなビルド」という言い方がされます、これはビルドをするために必要な環境の情報をDocker等を使用して構成管理の下に置くことで、ビルドの環境をBambooやJenkinsなどのCIサーバー上の環境とは疎結合にして、ビルドの独立性、安定性、スケーラービリティーを得ることを目的にしています。

コンテナー上でビルドを行う際に、ビルドのプロセスが単独で完結していればいいのですが、データベースなどの外部のサーバープロセスとの連携が必要になる場合もあります。そのための方法はいくつかありますが、ここではdokcer-composeを用いてコンテナ間の連携を行います。

このデモはAtlassian SummitのSummit 2015 - Docker, Continuous Integration, and You | Atlassianというセッションで紹介されたものの改良版で、外部コンテナーとしてPostgreSQLとElasticsearchを起動して連携しています。

デモレポジトリについて

デモに使ったレポジトリFork元に比べて

  • DockerのPostgreSQLイメージスキーマ初期化の仕様がかわったのでそれの対応
  • デモが作成された当時はdocker-composeがDockerに統合されておらずfigだったため、fig.ymldocker-compose.ymlにリネーム
  • 依存ライブラリを毎回ダウンロードしていてビルドに時間がかかるので、ローカル環境でキャッシュするようにした

という点に手を加えています。

Bambooの設定について

Bambooは以下のような構成になっています。

f:id:setoazusa:20151207124052p:plain:w200

docker-compposeのセットアップ

まずGitからコードを取得した後の、最初のステップはdocker-composeのセットアップになります。予めBambooサーバー上にdocker-composeがセットアップされている場合は不要です。

f:id:setoazusa:20151207133538p:plain

curl -L https://github.com/docker/compose/releases/download/1.2.0/docker-compose-Linux-x86_64 > docker-compose

chmod +x docker-compose

ディレクトリの初期化

次のステップは依存性をキャッシュするディレクトリの初期化になります。 f:id:setoazusa:20151207124221p:plain:w300

mkdir -p target/.m2
mkdir -p target/.lein

docker-composeによるビルド

f:id:setoazusa:20151207124324p:plain:w300

set -x

sudo ./docker-compose kill 
sudo ./docker-compose rm --force
sudo ./docker-compose build
sudo ./docker-compose up

この中では、docker-compose.ymlの設定にしたがってelasticsearchPostgreSQLのイメージを起動し、次にDockerfileに従ってアプリケーションのビルドを行っています。この際に、EXPOSEしているポートがオープンになるのとサーバーのプロセスがreadyになるのにタイムタグがあってたまにビルドがこけるので、ポートをポーリングするスクリプトを使ってコンテナの中のポートが立ち上がるのを待つようにしています。

ビルド結果の取得

f:id:setoazusa:20151207125734p:plain:w300

CID=`sudo ./docker-compose ps -q transfer`

sudo docker cp ${CID}:/code/testreports.xml .

sudo chown bamboo:bamboo testreports.xml

sudo docker cp  ${CID}:/home/transfer/.m2 target/

sudo docker cp  ${CID}:/home/transfer/.lein target/


sudo chown -R bamboo:bamboo target/

後処理としてDockerからテスト結果のxml(JUnit形式)ならびに依存性キャッシュをコンテナーからコピーする段取りになります。ここでコンテナーから取得した依存性のキャッシュを次回のビルドの時に戻すことによって、ビルド時間を節約しています。

テスト結果のパース

f:id:setoazusa:20151207130108p:plain:w300

前のプロセスで取得したテスト結果(testreports.xml)をここでパースしています。

CleanUp

f:id:setoazusa:20151207130302p:plain:w300

sudo ./docker-compose kill
sudo ./docker-compose rm -f

ここはコンテナの後始末になります。

ビルド結果

f:id:setoazusa:20151207130606p:plain:w400

はまりどころ

  • PostgreSQLのDockerイメージの仕様変更でビルドが走らなくなっていたため、発表の前日にデバッグしていたこと
  • Macbook ProVagrant上でBamboo+Dockerを動かしていたのですが、最初CPU×2、メモリ2Gにしたらelasticsearchにリアルタイム連携しているところが間に合わなくてテストがfailしたこと。CPU×3、メモリ4Gにしたら動いた。

最後に

Bamboo+docker-composeによるCIビルドの例でした。Atlassian Summitの事例報告と言うことでBambooを使った発表になりましたが、Bambooの特定機能には依存していないので、CIサーバーでのDockerの使用例の一つとしてみていただければと思います。