AndroidアプリをビルドするためのDockerfileを作る
/ 6 min read
Updated:Table of Contents
はじめに
業務で、Slack から GitHub Actions のトリガーを叩き、fastlaneを実行後、Firebase App Distributionにアップロードするというのをやりたいと思い、CI(GitHub Actions)上で動作するイメージを作成しました。結局自分しか使わないかつ、イメージのメンテナンスまで手が回らなくなり辞めちゃったのですが…
もちろん、テストも実行できます。
色々試行錯誤したので、どうやってやったか書いています。
実装
M1 Mac で Docker Desktop を使っています。また、Android SDK は再配布がダメなので、試すときは private にして試すなど、ご注意下さい。
ベースのイメージは、Ruby 公式のイメージを使っています。Ruby をベースイメージとしているのは、はじめにでも書きましたが、Slack から GitHub Actions のトリガーを叩き、fastlaneを使ってFirebase App Distributionにアップロードするというのをやっていたためです。が、イメージのメンテナンスなどまで手が回らなくなり結局 Bitrise に移行しましたが…
Ruby のイメージに関して、自分は最初知らなかったのですが、Ruby 公式の方がメンテしているのは、rubylangなのでこれを使っています。オフィシャルの Ruby イメージもあるのですが、そっちは Docker 公式のイメージみたいです。
FROM --platform=linux/amd64 rubylang/ruby:3.1.2-focal
ENV ANDROID_SDK_REVISION linux-8512546_latestENV ANDROID_SDK_ROOT /opt/android-sdk-linuxENV ANDROID_BUILD_TOOLS_VERSION 32.0.0ENV ANDROID_COMPILE_SDK 33
RUN apt-get update -y && \\ apt-get upgrade -y && \\ apt-get install zip unzip wget -y && \\ apt-get install openjdk-11-jdk -y
RUN wget <https://dl.google.com/android/repository/commandlinetools-${ANDROID_SDK_REVISION}.zip> && \\ unzip commandlinetools-${ANDROID_SDK_REVISION}.zip && \\ mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools && \\ mv cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest && \\ rm -r commandlinetools-${ANDROID_SDK_REVISION}.zip
ENV PATH ${PATH}:${ANDROID_SDK_ROOT}:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin
RUN mkdir ~/.android && \\ touch ~/.android/repositories.cfgRUN yes | sdkmanager --licensesRUN yes | sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" \\ "build-tools;${ANDROID_BUILD_TOOLS_VERSION}"1 行目で--platform=linux/amd64でプラットフォームを指定します。昔は intel の Mac を使っていたので特に指定しなかったのですが、今回は M1 Mac 上でビルドするため指定します。最終的に GitHub Actions で動かしたいのでつけました。
11 行目のopenjdk-11-jdkでは、JDK を入れます。
13-17 行目は、Android のcommandlinetoolsをダウンロード後、解凍します。ダウンロードするバージョンは公式サイトのCommand-line tools onlyから最新のバージョンを確認できます。
21-25 行目は、Android SDK と、build-tools をダウンロードします。repositories.cfgファイルは、これがないとWaring が出るため作成します。
実際にイメージを作成します。
docker build -t docker.pkg.github.com/tatsumi0000/android-playground/android-ci-image:latest .イメージ作成後、試しに手元でアプリのユニットテストを実行してみます。
docker run -it -v $PWD:/app docker.pkg.github.com/tatsumi0000/android-playground/android-ci-image:latest bash -c "cd /app && ./gradlew test"GitHub Packages にイメージを push します。docker loginが済んでいる前提です。
docker push docker.pkg.github.com/tatsumi0000/android-playground/android-ci-image:latest今回は動くかどうかだけ確認できればいいので、CI で使う workflows は以下のようにしています。
name: unit-test
on: - push
jobs: test: runs-on: ubuntu-latest
container: image: docker.pkg.github.com/tatsumi0000/android-playground/android-ci-image:latest credentials: username: USER_NAME ## イメージをprivateで公開するのでPATを発行しsecretsに設定する password: ${{ secrets.DOCKER_CONTAINER_REGISTRY_TOKEN }}
steps: - uses: actions/checkout@v2
- name: "unit test" run: | ./gradlew test最後に
Android の CI に使う Dockerfile 作成から、実際に GitHub Actions で動かしました。
実際に運用していたときは、GitHub Enterprise Server 上で動かしていて、まだキャッシュ機能がありませんでした。そのため、イメージ作成時に、ライブラリなどのキャッシュも含めることで、CI 時間を減らすようにしました(Dockerfile の最後にテストのステップを追加することで、キャッシュも含めました)。他にもイメージのキャッシュ更新も自動化していました。実装方法は単純で、master ブランチに対してpathsでapp/build.gradleを指定し、差分があると、CI 上でイメージを作成後、GitHub Packages に push するようにしていました。
Docker や CI は好きなのでもっと勉強していきたいなと思います。