はじめまして、SWETの金子(theoden9014)です。
今回のエントリーは2017-09-21に第一回目としてSWET主催で開催したAndroid Test Night #1と、そこで「Android SDK with Docker」という題で私が発表した内容についてご紹介したいと思います。
Test Night とは?
Test Nightとは、SWETが主催する主にテストに関係することについて語り合うことを目的とした勉強会です。
昨年11月からiOS Test Nightと呼ばれるiOSに特化したTest Nightを2ヶ月ごとに開催しています。 これまで合計39件の発表がおこなわれ、多数の方に参加していただき、活発な議論がおこなわれる勉強会になっています。
Android Test Night とは?
iOS Test Nightと同様にTest Nightで管理しているイベントです。 今回はAndroidについても同様にテストを対象としたイベントの需要があることがわかり、開催する運びとなりました。
Android Test Night #1
今回はその第1回目です。
15分枠のセッションでは
- 「コードレビューをより良くする Danger x Android」
- 「Androidのテストを効率的にするために考えたこと」
- 「Android E2E Testing at Mercari」
といった、開発プロセス改善についてのセッションや、実際にテストに取り組んでいる事例紹介のセッション。
5分枠のセッションでは
- 「AndroidSDK with Docker」
- 「JUnit5とAndroidのテスト」
- 「Kotlinで書かれたAndroidアプリをBazelでビルドする」
- 「Android CIをBitriseに移行して開発者・QAが幸せになったこと」
- 「Clean Architecture & TDD」
といった、CI、テストツールやテスト手法についてのセッション。 といった、様々な内容のセッションがありました。
当日の資料に関してはこちらにアップロードされているので詳細が気になる方はご覧ください。
Application Build with Docker
ここからは私が発表した「Android SDK with Docker」に話を移したいと思います。
あるアプリケーションをCIに載せようとした際、CIでアプリケーションのビルドを可能にする必要があります。
CI毎にビルドに関する設定方法や環境構築はまちまちで、複数のCIを利用する際はそれぞれのCIに対してビルド環境やビルドフローをメンテナンスする必要が出てきます。
近年のサーバーサイドアプリケーションはビルド環境や動作環境をDockerで統一化を図ることが主流となってきていますが、クライアントサイドアプリケーションではそういったアプローチに関する情報が少ない状態だと思います。
そこで今回はクライアントサイドでもDockerによるビルド環境の統一化ができないか検証してみました。
Android SDK with Docker
今回はAndroidアプリケーションに必要なビルド環境をコンテナイメージ化したAndroid SDK image
と、
そのAndroid SDK image
を元にアプリケーションコードを含めてビルドするApplication image
に分けたいと思います。
Android SDK image
を元にアプリケーションコードをmountしてビルドする手段もあります。
しかし、今回はgradleのキャッシュをイメージに含めたいので、Application image
を作る方向にしました。
Dockerのイメージレイヤーは以下の通りです。
alpine image | |-- Android SDK image | |-- Application image
Android SDK image
まずはAndroid SDKを利用できるDockerイメージが必要です。
ここで注意が必要なのはGoogleのAndroid SDK利用規約 (3.4)により、バックアップ目的以外でのコピー及び再配布が禁止とされている点です。 (gfxさんのこちらのブログ記事に詳細が言及されています)
つまり、Androidをビルドする為のDocker imageは自身でビルドする必要があるということです。
しかしながら、Dockerfile自体にAndroidSDKのライセンスは含まれません。
よって、Github上に公開されているものを利用するか自身で記述することでDockerfileを用意し、自身でDocker imageのビルドを行なってください。
Application image
こちらはAndroidアプリケーションと同じディレクトリ内にDockerfileを作成します。
ADD . /project
でアプリケーションコードをイメージに追加する前にgradleのキャッシュを生成しています。
これはDocker imageをビルドする際、命令によって変更が加わるまではDocker imageキャッシュが利用されるという仕様を利用し、最大限にDockerイメージのキャッシュを生かしています。
仮にADD . /project
の後にgradleのキャッシュを生成する処理をしてしまうと、
ADD
で追加するアプリケーションコードに変更が加わると、それ以降の処理はDockerイメージのキャッシュが利用されなくなります。
FROM ${ANDROID_SDK_IMAGE} RUN mkdir -p /tmp/gradle/app COPY gradlew /tmp/gradle/gradlew COPY gradle /tmp/gradle/gradle COPY build.gradle /tmp/gradle/build.gradle COPY gradle.properties /tmp/gradle/gradle.properties COPY settings.gradle /tmp/gradle/settings.gradle COPY app/build.gradle /tmp/gradle/app/build.gradle COPY app/mastiff.gradle /tmp/gradle/app/mastiff.gradle WORKDIR /tmp/gradle RUN ./gradlew ADD . /project WORKDIR /project RUN echo "sdk.dir=$ANDROID_HOME" > local.properties CMD ["./gradlew", "tasks"]
この状態で、
docker build -t application:$(git rev-parse HEAD) . docker run --rm -it \ -v $(pwd)/app/build:/project/app/build \ application:$(git rev-parse HEAD) \ ./gradlew build
と実行することで、アプリケーションをビルドすることが可能です。
登壇したセッションの資料にはAndroidエミュレータをDockerで起動しテストを行う方法も記載しております。しかし、エミュレータでのテストはパフォーマンスがよくないので、デバイスファーム等を利用すると良いと思います。
最後に
今回はクライアントサイドアプリケーションのDockerizeに関してご紹介しました。機会があればサーバーサイドアプリケーションのDockerizeについてもご紹介できればと思っております。
Android Test Night #2 の開催時期は未定ですが、2, 3ヶ月に1回程度開催を予定しておりますので、ご興味がある方は是非お待ちしております。
本ブログでは定期的にこういったテストにまつわる情報をアウトプットをしていきますので、是非本ブログをウォッチして頂ければと思います。
参考文献
- Test Night Group, https://testnight.connpass.com/
- Android Test Night #1 資料一覧, https://testnight.connpass.com/event/63753/presentation/
- Dockerfile reference, https://docs.docker.com/engine/reference/builder/
- 公開用DockerイメージにAndroid SDKを含めるのはライセンス違反という話, http://gfx.hatenablog.com/entry/2016/06/21/112404