CI
docker
docker-compose

dockerでテストするときのディレクトリ構成

TL;DR

別のイメージにいれる。

解決したいこと

dockerは仕様上、ビルドに含んだリソースは消せません。
でも、プロダクションコードに余計なテストコードを含めたくないですよね。
それを解決するためのディレクトリ構成です。

ディレクトリ構成

こんなんにしました。

project root
├docker-compose.yml
├src
│├Dockerfile
│├src_codes
│└unit_test
├test
│├Dockerfile
│└test_codes
├proxy
│├Dockerfile
│└nginx.conf
└db
  ├Dockerfile
  └DDL.sql

ディレクトリ説明

  • src -> 実際のプロダクトコードのイメージ用ディレクトリ
  • test -> テスト用イメージのディレクトリ
  • proxy -> ロードバランサ用イメージのディレクトリ
  • db -> RDB用イメージのディレクトリ

Dockerの仕様

Dockerでは、一度ビルドに含んでしまったリソースを消すのが、けっこうややこしいようです。
そもそも、ビルドしてテストした環境をそのままリリースできるというのがDockerのいいところでもあるので、テストが終わったらテストコードを消すというのは本末転倒な気もします。
しかし、特にe2eテストにはchromeのインストールが必要だったり、テスト用のツールもたくさん必要です。

解決法

単体テストなど、同一サーバ内で完結しないと難しいものは別として、テストコードはDockerの別イメージにします。テスト用のイメージを作るDockerfileを用意し、そのためのディレクトリを切っています。

そして、プロダクトコードのイメージ、テストコードのイメージをdocker-composeで管理します。
本番にはテストコードのイメージはデプロイせず、プロダクトコードのイメージのみデプロイします。

テストの考え方

テストは、以下の4つに分割して考えました。

  1. サーバサイドの単体テスト
  2. クライアントサイドの単体テスト
  3. apiテスト
  4. e2eテスト

この中で、1,2の単体テストはプロダクトコードのイメージですが、3,4はテストコードのイメージに含みます。
SPAで作った場合、JSONをかえすだけのURLも多いので、そういったテストはapiテストとして、テストコードイメージに含めました。
また、e2eテストはchromeやseleniumなどのツールが必要になるため、そういったモジュールをプロダクトコードに含めなくてすみました。

リバースプロキシ

また考え方にもよりますが、Nginxでリバースプロキシをたて、そこでssl化すれば、より簡単にhttpsでテストしやすくなります。
service workerはhttpsでないと動かないので、有効かと思います。

デプロイ

CIサーバでは、docker-composeでテストしたあと、プロダクトコードのイメージのみ、リポジトリにpushします。

docker-compose.yml
service-name:
  build: "."
  image: acount/project

上記のように、buildタグとimageタグを両方用意してビルドすると、イメージがビルドされるときに、imageタグに指定した名前をつけてくれます。
そうしておけば、docker-composeのサービス名でリポジトリにpushが可能です。

travis.yml
docker-compose push service-name

まとめ

docker-composeを使って、複数イメージで開発環境を整える記事は多かったのですが、テストに言及している記事はあまり見つかりませんでした。
ただこの構成はやってみると簡単で、かつ有効かとだなぁと感じました。