はじめに
今更Dockerデビューしたので、Androidアプリをビルドするために使用してみました。
今回作成するビルド環境は以下のような構成です。
- Bitbucketのリポジトリへのpushを契機にEC2上のJenkinsジョブを実行する
- JenkinsからAndroidビルド環境を持つDockerコンテナを立ち上げビルド実行
- JenkinsがcloneしてきたディレクトリをDockerコンテナからも参照する
- ビルドが終わったらコンテナを削除する
この記事では以下の範囲はカバーしないので予め設定しておいてください。
EC2インスタンスはAmazon Linuxで作成しています。
- EC2インスタンスを立てる作業
- EC2にssh接続する環境構築
EC2上にDockerを導入
まずはEC2上にDockerを導入します。Dockerイメージの作成などは後ほど。
# Dockerのインストール
$sudo yum update
$sudo yum install -y docker
# Dockerサービスの起動
$sudo service docker start
インストール後、ec2-userでdockerコマンド実行時にsudoをつけずに済むように以下を実行。
その後ログアウト/ログインしなおしてください。
$ sudo usermod -a -G docker ec2-user
【参考資料】
Mac OS XでAWS EC2のLinuxインスタンスにssh接続する
EC2上にJenkinsを導入
次にJenkinsを導入します。
以下にまとまっている手順を実行すればセットアップできるので一通り実施してください。
(ポートは8080のままいきます)
上記を行なった後、ブラウザからhttp://[EC2インスタンスのIPアドレス]:8080/
にアクセス
するとJenkinsの初期設定ページが出るので指示に従って設定完了してください。
EC2上にGitインストール
JenkinsでBitbucketからcloneする際にエラーが出るので、
もし入っていなければ以下でインストールしてください。
$sudo yum install git
JenkinsとBitbucketの連携設定
以下にまとまっている手順の1〜5の「ビルド・トリガ」でSCMをポーリングを選択」までを実施してください。
Jenkins用の鍵の生成とBitbucket との連携設定を一通り行うことができます。
BitbucketにpushされたらJenkinsで自動デプロイする
DockerfileとDockerイメージ作成
Dockerfile作成
EC2上の任意の場所にDockerfileを作成してイメージをビルドします。
今回はec2-userのホームディレクトリで作業しています。
$mkdir docker
$cd docker
$vim Dockerfile
ROM ubuntu:16.04
# Android 用のパッケージ
RUN apt-get update -y && \
apt-get upgrade -y && \
apt-get install git-core gnupg flex bison gperf build-essential zip curl \
zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev \
x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev \
libxml2-utils xsltproc unzip -y
# Java 用のパッケージ
RUN apt-get install software-properties-common python-software-properties -y
# JDKインストール
RUN apt-get -y update
RUN apt-get -y install openjdk-8-jdk || true
RUN apt-get -y install openjdk-8-jdk
# Android SDKをインストール
RUN cd /usr/local/ && \
curl -L -O \
https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip && \
unzip sdk-tools-linux-4333796.zip && \
/usr/local/tools/bin/sdkmanager --update && \
/usr/local/tools/bin/sdkmanager "platform-tools" && \
/usr/local/tools/bin/sdkmanager "build-tools;26.0.2" && \
/usr/local/tools/bin/sdkmanager "platforms;android-27" && \
/usr/local/tools/bin/sdkmanager "extras;android;m2repository" && \
/usr/local/tools/bin/sdkmanager "extras;google;m2repository" && \
/usr/local/tools/bin/sdkmanager "extras;google;google_play_services" && \
yes | /usr/local/tools/bin/sdkmanager --licenses && \
rm -rf /usr/local/sdk-tools-linux-4333796.zip
# 環境変数設定
ENV ANDROID_HOME /usr/local
ENV PATH $PATH:$ANDROID_HOME/tools
ENV PATH $PATH:$ANDROID_HOME/platform-tools
ubuntu16.04ベースでイメージを作成します。
build-toolsとplatformsのバージョンは自分のビルド環境に合わせて修正してください。
特に気をつける箇所はyes | /usr/local/tools/bin/sdkmanager --licenses
の所です。
この記述でdocker run
時にSDKの各種パッケージのライセンスに同意した状態になります。
パッケージのライセンスに同意すると/usr/local以下にlicensesというディレクトリが作成され、
その中にライセンス同意情報ファイル一式が作成されます。
もう一つの気をつける箇所はENV ANDROID_HOME /usr/local
の所です。
ビルド時にはANDROID_HOME以下にlicensesディレクトリがある前提でチェックされるため、
この設定が違うとライセンスに同意していない旨のビルドエラーが出てしまいます。
Dockerイメージ作成
Dockerfileができたら、以下コマンドを実行してandroid-ciという名前でDockerイメージを作成します。
$cd ..
$sudo docker build -t android-ci docker/
Dockerイメージ作成に成功した場合、docker images
コマンドで以下のように表示されます。
$sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
android-ci latest db6359ec1c3f 19 seconds ago 1.06GB
ubuntu 16.04 0b1edfbffd27 42 hours ago 113MB
ビルドスクリプト記述
docker run
の時にDockerコンテナ内から実行するビルドスクリプトbuild.shを記述します。
JenkinsでCloneすると/var/lib/jenkins/workspace
下にプロジェクトができるので、
Clone後にプロジェクトディレクトリにコピーしやすいように/var/lib/jenkins/workspace
下にbuild.shを作成します。
#!/bin/bash
./gradlew clean && \
./gradlew dependencies && \
./gradlew assembleDebug
build.shを保存したら実行権限を付けておきます。
$sudo chmod 777 build.sh
Jenkinsのビルドシェル記述
Jenkinsでdockerコマンドを実行するときsudoしなくて良いように以下を実行します。
$sudo usermod -a -G docker jenkins
Jenkinsジョブ設定で[ビルド手順の追加]->[シェルの実行]を選択しシェルスクリプトに以下を記述する。
cd ${WORKSPACE}
cp ../build.sh ./
chmod 777 gradlew
docker run -i --rm -v ${WORKSPACE}:/workspace -w /workspace android-ci sh build.sh
上のスクリプトではdockr run
を以下の設定で実行しています。
-
docker run
時に--rmを指定することでbuild.sh終了後にコンテナが削除されるようにする - ホストマシン(EC2)のWORKSPACE(
/var/lib/jenkins/workspace/プロジェクトディレクトリ
)をDockerコンテナ上の/workspaceにマッピングして共有ディレクトリとして使用する - android-ciイメージからコンテナを作成し、その上でbuild.shを実行する
ここまで設定したら、Jenkinsジョブで設定したリポジトリ・ブランチに変更をpushしてみましょう。
pushを契機にJenkinsでジョブが実行され、ビルド成功することが確認できるはずです。
おわりに
Docker、環境使い捨てできるのがとても便利だなと思いました。
ずぼらで環境汚しがちな人間なので積極的に活用していきたいところです。
プルリク契機でビルドする方法も調べてみようと思います。