そこで一念発起して、Docker イメージを使った CI に切り替えることにしました(実行環境としては引き続き Travis を使います)。
その際に、要件として以下のようなことを考えました。
- CI以外に、コミット前のテストにも使えるようなイメージにすること
- コマンド一発でビルドとテストが動作すること
- 無駄な処理をしないこと
その結果、以下のような実装になりました。
- テストに必要なソフトウェア群をインストールしたイメージを Docker Hub にアップロードしておく
- テストには、1. テスト用コンテナにコードのあるディレクトリをマウントし、2. アウトオブトリービルド注1とテストを実行するスクリプトを書く
- CI環境では、そのスクリプトを実行する
- 開発者がローカルでそのスクリプトを実行してテストしてもよい
Dockerfile および CI 実行用のスクリプトは、H2O のレポジトリにある以下のファイルです。
結果、Docker 導入前に90行あった .travis.yml は23行にまで短くなり、また、CI に必要な時間も2割ほど減少しました(CI を実行するたびに、必要なソフトウェアをビルドする手間が不要になったため)。
また、開発者が各個人の環境において
make -f misc/docker-ci/check.mk
と make
を実行するだけで、いつでも(コミット前でも)CI 環境と同様のテストが実行できるようになりました。テストが失敗したら、コンテナを立ち上げっぱなしにして、ローカルでコード修正&特定のテスト再実行を繰り返すことも可能なので、バグ修正が捗ります。まとめ:CI 用の Docker イメージを作るのではなく、テスト用の CI イメージを作り、それを CI に展開すべき
言わずもがなかもしれませんが、備忘録としてまとめておきます。
注1: ソースディレクトリ以外の場所に生成物を配置するビルド手法のこと。アウトオブトリービルドができない場合はaufsを使っても良いのかもしれない