skip to content
私的歌詞倉庫

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_latest
ENV ANDROID_SDK_ROOT /opt/android-sdk-linux
ENV ANDROID_BUILD_TOOLS_VERSION 32.0.0
ENV 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.cfg
RUN yes | sdkmanager --licenses
RUN 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 ブランチに対してpathsapp/build.gradleを指定し、差分があると、CI 上でイメージを作成後、GitHub Packages に push するようにしていました。

Docker や CI は好きなのでもっと勉強していきたいなと思います。

参考サイト