wercker が最近 Docker に対応しました。 これにより、 Docker を利用している場合にはテストからデプロイまでを共通したコンテナでおこなえるほか、既存のコンテナを再利用し、柔軟に組み合わせて利用できるようになりました。
最近 Aerospike という超優秀な KVS を利用しているのですが、 Docker ベースになった werkcer 上でこのクライアントライブラリのユニットテストを実行したいと思ったので試してみました。
werker には services という、 複数のコンテナを外部サービスとして利用する仕組みがあります。この機構により、使用するミドルウェアのコンテナイメージを用意すれば、 CI 時にそれを利用したテストを走らせることができます。素晴らしい仕組みです。たとえば、 Redis を使用したければ、wercker.yml
の services
セクションに以下のように redis
を追記します。
1 | services: |
これにより、 CI 時に Docker Hub の Redis イメージが pull されてきて、 アプリケーションから利用できるようになります。 Aerospike を使う場合も同様で、 wercker.yml
に以下のように書きます。
1 | services: |
こうすると、ビルド時に Docker Hub の aerospike リポジトリからイメージを取得して、利用できるようにしてくれます。
では、アプリケーション側からこれらのサービスにアクセスするにはどうすればよいのでしょうか?
wercker では Docker のコンテナ間リンク機構 を利用して、 環境変数が自動で準備されるようになってます。 Aerospike を使用した場合には、以下のような環境変数が用意されることになります。
1 | AEROSPIKE_ENV_AEROSPIKE_SHA256=df810e67d363291f6f40c046564bbc7ab775fcdb45ebfb878368361705063015 |
ドキュメント にある通り、環境変数の命名規則は
1 | <name>_PORT_<port>_<protocol> |
をプレフィックスとして、 prefix_ADDR
なら IP アドレス、 prefix_PORT
ならポート番号、 prefix_PROTO
ならプロトコル名になっています。なおかつ、Aerospike の Dockerfile が実行されるので、 3000 ~ 3003 番のポートに対応する環境変数がそれぞれ用意されていますね。
したがって、あとはアプリケーション側が環境変数から必要な値を取得するような実装になっていればよいことになります。たとえば Go 言語であれば、 以下のように os.Getenv()
を使えばよいでしょう。
1 | addr := os.Getenv("AEROSPIKE_PORT_3000_TCP_ADDR") |
これで、 DB などの外部サービスに依存したテストも wercker 上で実行できるようになりました!