Jenkins with DockerをDockerコンテナとして配布する

Jenkins with Docker in Docker
----------------------------

この記事ではDockerでJenkins with Dockerを動かす方法について記載します。
今回利用したイメージは[こちら](https://registry.hub.docker.com/u/koduki/jenkins-with-docker/)です。

はじめに
----------------

JenkinsでDockerを使うことでDrone.ioのようにジョブ毎の環境分離ができとても便利です。
その辺りの詳細は「[第8回Jenkins勉強会で「Jenkins with Docker」というLTをしました](http://techblog.yahoo.co.jp/event/jenkins-with-docker/)」に記載されています。。

ただ、Jenkins with Dockerでジョブ毎の環境分離が出来るのは良いのですが、どうせなら、CI環境自体もコンテナとしては配布したいですよね？
環境のポータビリティこそがDockerのポイントなので。

というわけで、以下にその方法を記載していきます。

Docker in Docker
--------------------

そもそも、DockerコンテナでJenkinsを配布して、そのJenkinsがDockerを実行するということは、Dockerの中でDockerを実行する必要があります。そんなこと出来るんでしょうか？

実はで出来ます。特権モード (privileged)を使うことで、Dockerコンテナ内からDockerコンテナを操作することが出来るようになります。
詳細は[こちら](http://blog.docker.com/2013/09/docker-can-now-run-within-docker/)を参照。

使い方は簡単で、

```
docker run --privileged -it jpetazzo/dind
```

とすることで、dockerコンテナの利用出来るコンテナに入れるので、通常どおり

```
docker run -it koduki/centos7 /bin/bash
```

とかすれば、Dockerコンテナが起動します。これは仮想マシンのようにDockerの上にDockerを作ってるのではなく、Dockerから別のDockerを操作する形になるので、ホストOSからもプロセスの起動を確認できます。

```[bash]
% ps aux|grep docker|grep centos
root     26726  0.0  0.3 264076 11480 pts/4    Sl+  22:39   0:00 docker run -it koduki/centos7 /bin/bash
```

Jenkinsのインストール
------------------------

jpetazzo/dindはubuntuベースなのでapt-getを使ってJenkinsをインストールすることが出来ます。以下のようなDokcerfileになります。

```
FROM jpetazzo/dind
MAINTAINER koduki

# Install Jenkins
WORKDIR /tmp
RUN wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
RUN echo 'deb http://pkg.jenkins-ci.org/debian binary/' >> /etc/apt/sources.list
RUN apt-get -y update
RUN apt-get -y install jenkins
RUN apt-get clean

# Add Jenkins jobs
ADD resources/simple-test01/ /var/lib/jenkins/jobs/simple-test01/

# Run
WORKDIR /var/lib/jenkins
ENTRYPOINT java -DJENKINS_HOME=/var/lib/jenkins -jar /usr/share/jenkins/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8000
```

ただ、この方法だとDockerデーモンを起動できないので、Jenkinsと同時にwrapdockerを起動する必要があります。
そのため、下記のようなrun.shを作り

```[bash]
#!/bin/bash

/usr/local/bin/wrapdocker &
java -DJENKINS_HOME=/var/lib/jenkins -jar /usr/share/jenkins/jenkins.war --webroot=/var/cache/jenkins/war --httpPort=8000
```

この形で実行します。

```[bash]
# Run
ADD resources/run.sh /tmp/run.sh
ENTRYPOINT /tmp/run.sh
```

実行はポート8000番をforwardしたいので

```
docker run --privileged -p "8000:8000" -it koduki/jenkins-with-docker
```

でprivileged を付けての実行となります。

Jenkins with Dockerの設定
--------------------------

Jenkins with Dockerの設定です。とはいえ、設定と言っても、今回はプラグイン等を作るわけではないので、ジョブの中でDockerを呼ぶだけです。
上のDockerfileにも記載していますが、/var/lib/jenkins/jobs/ 以下にジョブ用のディレクトリを作成し、config.xmlを作成します。

１から手で作るのは大変はのでJenkinsでGUIで作成したものを `docker exec -it ${container_id} bash` とかでcat等で取得してコピーするのがらくだと思います。
サンプルで作ったコンテナでは下記のようなファイルになりました。

```[xml]
<?xml version='1.0' encoding='UTF-8'?>
<project>
  <actions/>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.scm.NullSCM"/>
  <canRoam>true</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers/>
  <concurrentBuild>false</concurrentBuild>
  <builders>
    <hudson.tasks.Shell>
      <command>WORKDIR=`pwd`
        echo &apos;Hello Docker.&apos;

        # Run Docker Container.
        docker run koduki/centos7 &apos;\

        cat /etc/redhat-release ;\
        ls -l \
        &apos;
      </command>
    </hudson.tasks.Shell>
  </builders>
  <publishers>
  </publishers>
  <buildWrappers/>
</project>
```

これでJOBを実行したさいにcatとlsがコンテナ内で走ります。

まとめ
-----------------------

Dockerコンテナを利用するJenkinsをDockerコンテナで配布する方法について記載しました。
Dockerコンテナの管理層を含んだ環境を配布したいときには非常に便利だと思います。

通常は、そういったレイヤーはk8sとかが賄うのであまり気にすることはないかもしれませんが、ちょっとした検証用の環境をまるごと配布するとかには向いてる気がします。

それではHappy Hacking!

参考
----------------------

- [DOCKER CAN NOW RUN WITHIN DOCKER](http://blog.docker.com/2013/09/docker-can-now-run-within-docker/)
- [Docker in Docker - dokku-alt](http://qiita.com/algas/items/b9a3e7347b5945697587)
- [DockerコンテナでJenkinsを動かす](http://qiita.com/sokutou-metsu/items/4a2c9636c9e6974e2919)
- [第8回Jenkins勉強会で「Jenkins with Docker」というLTをしました #jenkinsstudy](http://techblog.yahoo.co.jp/event/jenkins-with-docker/)