android アプリビルド用 jenkins を docker で構築する

# 対象読者

* android アプリケーションをコマンドラインでビルドする環境をサクッと構築したい

# Dockerfile と必要ファイル

## ディレクトリ構造

```
android-sdk/
  ┗android-sdk_r24.4.1-linux.tgz
jdk/
  ┗jdk-8u40-linux-x64.rpm
keystore/
  ┗test.keystore
Dockerfile
jenkins.sh
supervisord.conf
```

## ファイル解説

### android-sdk

sdk はdocker イメージのビルド時に WEB から取得してもいいのですが、旧バージョンの sdk は android developers サイトからリンクが消えてしまうことがあるので、ダウンロードして置いておきます。

### jdk

oracle JDK を使いたいのでダウンロードして置いておきます。

### keystore

リリース版を作成するために使用します。

### Dockerfile

ちょっと長いので後述します。

### jenkins.sh

jenkins の起動スクリプトです。

```
#!/bin/bash
set -e
exec java $JAVA_OPTS -jar /usr/share/jenkins/jenkins.war $JENKINS_OPTS "$@"
```

### supervisord.conf

※jenkins しか動かさないので supervisord は必須ではないです。

```	
[supervisord]
nodaemon=true

[program:jenkins]
user=jenkins
command=/usr/local/bin/jenkins.sh
stdout_logfile=%(ENV_JENKINS_HOME)s/stdout.log
stderr_logfile=%(ENV_JENKINS_HOME)s/stderr.log	
environment=HOME="/var/lib/jenkins",USER="jenkins"
```

## Dockerfile

※別件で作成した Dockerfile を流用したので、無駄なものも含まれているかもしれません。
※android の build-tools などはその時点での最新のものに変更してください。target api は適宜変更してください。
※jenkins 起動部分は https://github.com/jenkinsci/docker を参考にしています。

```
FROM centos:7
MAINTAINER hoge <hoge@hoge.hoge>


# Proxy for build
ENV NO_PROXY localhost,127.0.0.1
ENV no_proxy ${NO_PROXY}
ENV HTTP_PROXY プロキシ環境下でビルドする場合は必要です
ENV HTTPS_PROXY ${HTTP_PROXY}
ENV http_proxy ${HTTP_PROXY}
ENV https_proxy ${HTTP_PROXY}
RUN cp /etc/yum.conf /tmp/yum.conf.bak && echo proxy=${HTTP_PROXY} >> /etc/yum.conf


# Locale
RUN yum reinstall -y glibc-common \
 && localedef --quiet -c -i ja_JP -f UTF-8 ja_JP.UTF-8 \
 && rm -f /etc/localtime \
 && ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
ENV LANG ja_JP.UTF-8



############### install tools(jdk etc...) ####################
RUN yum -y update && yum install -y wget git curl zip unzip gcc gcc-c++ make bzip2 libstdc++.i686 zlib.i686 openssl file which

# git
RUN git config --system user.email "jenkins@localhost" \
 && git config --system user.name "jenkins"

# jdk
COPY jdk /tmp/jdk
WORKDIR /tmp/jdk
## jdk 8u40
RUN rpm -ivh --force jdk-8u40-linux-x64.rpm \
 && rm jdk-8u40-linux-x64.rpm
# set default java
ENV JAVA_HOME /usr/java/jdk1.8.0_40/
RUN ln -sf /usr/java/jdk1.8.0_40/bin/java /usr/bin/java \
 && ln -sf /usr/java/jdk1.8.0_40/bin/javac /usr/bin/javac

# svn
WORKDIR /usr/src
RUN yum install -y apr-util-devel sqlite-devel zlib-devel
RUN wget http://www.webdav.org/neon/neon-0.29.0.tar.gz \
 && tar xvf neon-0.29.0.tar.gz \
 && cd neon-0.29.0 \
 && ./configure \
 && make \
 && make install \
 && cd ../ && rm -rf neon-0.29*
RUN wget http://archive.apache.org/dist/subversion/subversion-1.6.11.tar.gz \
 && tar xvf subversion-1.6.11.tar.gz \
 && cd subversion-1.6.11 \
 && ./configure \
 && make \
 && make install \
 && cd ../ && rm -rf subversion-*

# ant
WORKDIR /usr/src
RUN wget http://ftp.meisei-u.ac.jp/mirror/apache/dist//ant/binaries/apache-ant-1.9.7-bin.tar.gz \
 && tar xvf apache-ant-1.9.7-bin.tar.gz && rm -f apache-ant-1.9.7-bin.tar.gz \
 && mv apache-ant-1.9.7 /usr/local/ant \
 && wget http://search.maven.org/remotecontent?filepath=junit/junit/4.12/junit-4.12.jar -O /usr/local/ant/lib/junit.jar
ENV PATH=${PATH}:/usr/local/ant/bin


# android sdk
WORKDIR /usr/src
COPY android-sdk/ ./android-sdk
RUN tar xzvf android-sdk/android-sdk_r24.4.1-linux.tgz -C /usr/local/ && rm -rf android-sdk
ENV PATH $PATH:/usr/local/android-sdk-linux/tools/
# target
RUN  echo y | android update sdk -a -s --no-ui --proxy-port プロキシのポート番号 --proxy-host プロキシのホスト \ 
 -t build-tools-23.0.2,build-tools-20.0.0,android-23,android-17,android-10,android-7,android-3,platform-tools
RUN  echo y | android update sdk -a -s --no-ui --proxy-port プロキシのポート番号 --proxy-host プロキシのホスト \ 
 -t extra-android-support
# android ndk
WORKDIR /usr/src
RUN wget http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin \ 
 && chmod a+x android-ndk-r10e-linux-x86_64.bin && sync \
 && ./android-ndk-r10e-linux-x86_64.bin \
 && mv android-ndk-r10e /usr/local/ \
 && rm -f android-ndk-r10e-linux-x86_64.bin


# key
COPY keystore /opt/keystore 

################## set up Jenkins ##########################

ENV JENKINS_VERSION 1.625.2
ENV JENKINS_SHA 395fe6975cf75d93d9fafdafe96d9aab1996233b

ENV JENKINS_HOME /var/lib/jenkins
RUN useradd -d "$JENKINS_HOME" -u 1001 -m -s /bin/bash jenkins


# jenkins
RUN mkdir -p /usr/share/jenkins/

RUN curl -fL http://mirrors.jenkins-ci.org/war-stable/$JENKINS_VERSION/jenkins.war -o /usr/share/jenkins/jenkins.war \
  && echo "$JENKINS_SHA /usr/share/jenkins/jenkins.war" | sha1sum -c -

ENV JENKINS_UC https://updates.jenkins-ci.org
RUN chown -R jenkins "$JENKINS_HOME"

# set up privilege
RUN chgrp -R jenkins /usr/local/android-ndk-r10e/


################### set process ##################
RUN yum install -y epel-release
RUN yum install -y supervisor

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# for main web interface:
EXPOSE 8080
COPY jenkins.sh /usr/local/bin/jenkins.sh


CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]


################### clear #######################
WORKDIR /home/jenkins
RUN cp /tmp/yum.conf.bak /etc/yum.conf

```

# Docker コンテナの起動

特にこれと言って変わったことはないです。

## イメージを作成

※イメージ名を myJenkins:0.1 としています。

```
docker build -t myJenkins:0.1 .
```

## コンテナを起動

※ホストの /tmp/hoge を jenkins のホームディレクトリとしてマウントしています。
※ホストマシンで uid 1001 のユーザを作成して、/tmp/hoge の owner に設定する必要があったかもしれません。

```
docker run -p 8080:8080 -v /tmp/hoge:/var/lib/jenkins -d myJenkins:0.1
```

上記では /tmp/hoge に jenkins のジョブ設定や成果物が格納されます。
実運用する場合は適切なディレクトリに変更して、バックアップ対象としてください。

## 確認する

Docker コンテナを起動したホストマシンの 8080 ポートにアクセスすると、jenkins が稼動しているはずです。

# ビルドする

ビルドツールが gradle の場合、以下のコマンドで apk ファイルを作成できます。

```
chmod +x gradlew

# docker ホストが proxy 配下にある場合は proxy の設定が必要です。
cat << EOF > gradle.properties
systemProp.http.proxyHost=プロキシホスト
systemProp.http.proxyPort=プロキシポート
systemProp.https.proxyHost=プロキシホスト
systemProp.https.proxyPort=プロキシポート
EOF

cat << EOF > local.properties
ndk.dir=/usr/local/android-ndk-r10e/
sdk.dir=/usr/local/android-sdk-linux/

key.store=/opt/keystore/test.keystore
key.store.password=keystoreのパスワード
key.alias=エイリアス
key.alias.password=エイリアスのパスワード
EOF

export TERM=dumb
export GNUMAKE=/usr/bin/make


./gradlew assembleRelease
```

# まとめ

誰かのお役に立てば幸いです。