Androidエンジニアは自分専用のDockerイメージを作るべきだと思った
初めてDockerイメージを作ったのでエントリに書いておきます。タイトルはすこし言い過ぎな感じはありますが、CIにDocker使っている人は自分でDockerイメージ作った方がいいよねって話です。
私とCI
CIという言葉もかなり広まり、会社で使うだけではなく個人の開発でもCIを導入している人は多いのではないでしょうか。私はVPN + JenkinsでCIを始めて、1年半前にWerckerに乗り換えました。Jenkinsにはとてつもない自由さやCIがコケた時に原因究明が楽な点がありますが、メンテナンスが大変でした。CIサービスはメンテナンスがあまり必要なくてとても気に入ってます。
Werckerのメリットについては他に書かれている方がたくさんいるので、適当にググって読んでみてください。
WerckerとDocker
私がWerckerに移行した当時はBoxと呼ばれる実行環境でビルドするようになっていましたが、少し前からDockerに差し替わりました。Dockerというキーワードは知っていたもののイメージを作ったことも使ったこともなかったので、適当にイメージを探して他の人のイメージを使わせてもらっていました。しばらくはそれで大丈夫だったのですが、最近この辺でストレスが溜まるようになってきました。
ストレスの原因
一番の理由はAndroidのbuild toolやサポートライブラリのアップデートについていくために実行環境のアップデートをしないといけないのですが、他人のイメージを使っているがために、なかなかアップデートすることができないところです。Dockerfileはオープンソースで公開されているんだからPR出せばいいじゃんという声も聞こえてきそうですが、PRを出したとしてもすぐにマージされるわけではないので、そこでストレスが溜まってしまいます。他の人のライブラリや環境を使うなら当然のリスクですが、プライベートで開発できる時間は限られています。こういった待ち時間があるとついついモチベーションが落ちがちなのでどうにかしたいです。
環境の変化
Android誕生してからもう少しで10年経とうとしていますが、その開発環境は決して枯れることはなく常に変化しています。今もJack and JillやOpen JDK移行などが迫ってきており、今後も開発環境の決定版といえるものはでてこないと思います。
使いたいパッケージの違い
また、人によって使いたいパッケージは異なります。私の場合、CIが終わった後にSlackで通知をしたく、そういったプラグインを使っているのですが、そのプラグインがRubyで書かれているためRubyをインストールする必要があります。こういった要望はなかなかPRにすることはできません。
そして自分のDockerイメージを作った
というわけでこのストレスを解消すべく自分でAndroidアプリのビルドができるDockerイメージを作りました。
作ったイメージはdocker hubに公開したので、試してみたいという方はどうぞ
https://hub.docker.com/r/tomorrowkey/wercker-container-android/
DockerfileもGitHubに公開しました。
できるだけ最新のものにアップデートしていきますしそういったPRも大歓迎ですが、ベストエフォートなのであしからず。そこでストレスが溜まってきたら自分のイメージを作るいいタイミングだと思います。私のリポジトリをforkしてもいいですし、一から作るのもDockerを理解することができると思うのでおすすめです。
メモ
以下、イメージを作るにあたってどう解決したかメモを残しておきます。
OS
FROM ubuntu:14.04
ベースはAndroidのビルド環境によく使われるUbuntuにした。
Oracle Java8のインストール
# Java8 installation RUN \ apt-get install -y software-properties-common curl && \ add-apt-repository -y ppa:webupd8team/java && \ apt-get update -y && \ echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \ apt-get install -y oracle-java8-installer
oracle-javaのインストールはapt-getに新しくリポジトリを追加することでできると知った。
How To Install Oracle Java 8 In Debian Via Repository [JDK8] ~ Web Upd8: Ubuntu / Linux blog
リポジトリ追加したらapt-get update
してインストール可能なソフトウェアの更新が必要なところに注意
echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
と書かれているところは使用許諾の同意に必要。
Docker上でOracle Javaの実行はライセンス違反の可能性があるとの情報を得たのでOpen JDKを使うように修正しました。
Dockerコンテナ上でのJavaの実行はライセンス違反なのか?
RUN \ apt-get install -y software-properties-common curl && \ add-apt-repository -y ppa:openjdk-r/ppa && \ apt-get update && \ apt-get install -y openjdk-8-jdk
OpenJDK8もppaの追加が必要なので、add-apt-repository
を使ってインストール。以前OpenJDKを使ったときにビルドできないなどの不具合があった気がしたが、いまのところ問題なさそうなのでしばらくこれでやってみようと思います。
Android SDKのインストール
# Android SDK Installation ENV ANDROID_SDK_REVISION r24.4.1 RUN \ cd /usr/local && \ curl -L -O "https://dl.google.com/android/android-sdk_$ANDROID_SDK_REVISION-linux.tgz" && \ tar -xf "android-sdk_$ANDROID_SDK_REVISION-linux.tgz" && \ rm "/usr/local/android-sdk_$ANDROID_SDK_REVISION-linux.tgz" RUN apt-get install -y lib32z1 lib32gcc1
Android SDKのインストールはアーカイブをダウンロードして、配置すればよいと思っていたが、aaptが使うパッケージが足りなかったみたいなので、追加でlib32z1
とlib32gcc1
をインストールしている。実際にCIでビルドしようと思っていたアプリをビルドしてみたらaaptがエラーを吐いていたので何か足りないんだなと分かった。あとは適当に調べてパッケージをインストールした。
androidコマンドがなくなる
RUN echo y | android update sdk --no-ui --force --all --filter "tools" RUN echo y | android update sdk --no-ui --force --all --filter "platform-tools"
toolsとplatform-toolsを同時にインストールしようとしたが、そしたらandroidコマンドがなくなるという不具合に出会った。別にインストールすると問題なかった。
Rubyのインストール
# Ruby installation RUN add-apt-repository -y ppa:brightbox/ruby-ng && apt-get update && apt-get install ruby
ビルド終わった後にSlackで通知するようにしているのだが、そのプラグインにRubyが必要なのでインストールしている。
当初はrbenvを使ってRubyをインストールするように実装してみたが、rbenvはexport
で環境変数を設定しようとする。Dockerではビルド中にexport
しても無視されてしまうので、素直にrbenvを使うことができない。ではDockerで環境変数を設定するにはどうするかというとENV
を使わなければならない。どうにかスクリプトに書き込むことでrbenvを使うことができるようになったが、CI上ではパスが通らなくて調査困難で諦めた。
Rubyのインストールも新しくリポジトリを追加しないといけなかったので、追加してる。
Ruby packages for Ubuntu - Brightbox Cloud
apt-add-repository vs add-apt-repository
リポジトリの追加するコマンドはapt-add-repository
とadd-apt-repository
があるみたいで、どう違うか調べた。どちらも一緒らしいので、add-apt-repository
を使うように揃えた。
Dockerコマンドとか
docker-machineの起動
docker-machine start default
Dockerfileのビルド
docker build .
イメージの列挙
docker images -a
イメージの起動
docker run -it <IMAGE_ID>
コンテナの列挙
docker ps -a
コンテナの停止
docker rm <CONTAINER_ID>
全コンテナの停止
docker ps -aq | xargs docker rm
ネットワークが繋がらなくなる
ルノアールにてdocker buildしようとしたらネットワークが不通になることに少しだけハマった。詳しくはよくわからないが、接続するネットワークが変わったことが原因っぽい。docker-machine restart
で再起動すると治った。