DockerでRuby on RailsのCI環境を作ろうとした話

少し前にCIサーバーとして使っていたMac miniがお亡くなりになり、CIサーバーどうしようと考えていました。 Dockerを使いCI環境を作り、さくらのクラウドにあるステージング用のサーバーで動かせば良いのでは! と思い立ち土日に挑戦してみました。

Docker

Mac上でCI環境を作る

Docker ToolboxをインストールすればDockerMachineやDocker Client(dockerコマンド)、VirtualBoxなどがインストールされます。

とりあえず、何も考えず docker-machine コマンドで Docker用のサーバー(環境)がVirtualBox上に立ち上がります。

$ docker-machine create -d virtualbox

オプションを指定してDockerサーバーメモリーやCPU数を増やしたりもできます。

後は docker コマンドを使い、Dockerイメージを作ったり、走らせたりして環境を作ります。 Dockerイメージへのアプリのインストール等の作業はDockerファイルに書きます。

CI環境作り

今回作るのは普通のRuby on RailsアプリのRSpecをJenkins上で実行します。そこで必要になるものは、

Rubyのインストールは Jenknsの rbenv Plugin がインストールしてくれるので環境には、OS標準のRubyを入れておけば良いです。

Ruby on Railsはご存知のように bundler がインストールしてくれるので、C言語拡張ライブラリーが構築できる環境があればOKです。

1. Jenkinsの公式Dockerイメージ

Jenkinsの公式Dockerイメージ が公開されています。これをベースにすれば楽じゃないか!

当然、Jenkinsは動きますが PostgreSQLインストールで ja_JP.UTF-8 ローケールを作ろうとしたのですが上手くいきません・・・ いろいろとトライしたのですがベースのUbuntuが通常とは異なるようであきらめました。

2. Java Runtime Environment がインストール出来ない !

JenkinsはJavaで出来ているので Java Runtime Environment (JRE) が必要です。apt-getでJenkinsをインストールすると依存関係から OpenJDK がインストールされるのですがインストール中の

Setting up ca-certificates-java ....

で止まってしまいます。仕方ないので、まずは OracleJREを以下のようなDockerfileインストールしていました。

RUN apt-get install -y software-properties-common
RUN add-apt-repository -y ppa:webupd8team/java
RUN apt-get update
RUN echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 boolean true" | debconf-set-selections
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get install -y oracle-java7-installer

でもなぁ〜 と思い、いろいろ検索していたら qiita に解決方法がありました。 Dockerサーバーを作るさいに以下のようなオプションを指定すれば上手くいきます。

$ docker-machine create --driver virtualbox --engine-storage-driver overlay dev

3. やっぱりsshdは必要

Docker内にはsshdを立ち上げてsshログインしたりせず、ログ・ディレクトリー等をホストのディレクトリーにバインドシして使うべきだ! という考え もあるようですが、やはり上手くいかない時の調査ようにsshログインできた方が良いですよね。

USER root
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:パスワード' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

を Dockerfileの最後に書いておくとsshログイン出来ます。rootでログインするのは気持ち悪いですが・・・ 最終的な環境でネット上からはsshできないようにiptables(Firewall)等で制限しておいて下さいね。

4. 出来ました!

Dockerfile は以下のようになりました

FROM ubuntu:14.04
USER root

# IMPORTANT http://qiita.com/moutend/items/18682948811175ed0e1d
# docker-machine create -d virtualbox --engine-storage-driver overlay NAME

RUN apt-get update 
RUN locale-gen ja_JP.UTF-8
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

## Libs
RUN apt-get install -y wget git-core ruby build-essential bison flex sqlite3 autoconf  \
 libreadline6-dev zlib1g-dev libssl-dev libyaml-dev libxml2-dev libxslt1-dev libncurses5-dev libsqlite3-dev

## Tools
RUN apt-get install -y fonts-takao-mincho libfontconfig1-dev libicu-dev libfreetype6 libpng-dev libjpeg-dev
RUN wget -O /usr/local/bin/phantomjs https://github.com/Pyppe/phantomjs2.0-ubuntu14.04x64/raw/master/bin/phantomjs
RUN chmod 755 /usr/local/bin/phantomjs 

## PostgreSQL
RUN apt-get install -y postgresql-9.3 libpq-dev postgresql-client-9.3 postgresql-contrib-9.3
RUN sed -i 's/local\s*all\s*all\s*peer/local\tall\tall\tmd5/' /etc/postgresql/9.3/main/pg_hba.conf
USER postgres
RUN /etc/init.d/postgresql start &&\
    psql --command "CREATE USER テストアカウント WITH CREATEDB PASSWORD 'パスワード';" &&\
    psql --command "CREATE DATABASE テスト用データベース WITH OWNER テストアカウント TEMPLATE template0 ENCODING 'UTF8' LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8';"

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

## SSH
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
RUN echo 'root:パスワード' | chpasswd
RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
EXPOSE 22

## Startup
COPY startup.sh /usr/local/bin/startup.sh
ENTRYPOINT ["startup.sh"]
  • startup.sh は
#!/bin/bash

/etc/init.d/postgresql start
/etc/init.d/jenkins start

/usr/sbin/sshd -D

5. クラウド上のUbuntuで動かない!

クラウド上の UbuntuサーバーにDocker環境 を作り、Mac上で作ったDockerイメージをsave, load したのですがなぜか PostgreSQLが起動しません (Jenkins, sshd は起動されます)。

# /etc/init.d/postgresql start
Starting PostgreSQL 9.3 database server                                                                                                                       * The PostgreSQL server failed to start. Please check the log output:
2014-12-01 17:41:37 UTC FATAL:  could not access private key file "/etc/ssl/private/ssl-cert-snakeoil.key": Permission denied

調べてみると、ここにissue がありました。 しかし、解決しませんでした・・・・ 疲れた ・・・

Dockerの完成度はこんなものなのでしょうか???

今回の結論

というわけで、ステージングサーバーにJenkinsを直接インストールしました ^^);

ステージングサーバーのruby(gem)は /usr/local/ にインストールされているので、Jenkinsのrbenvとは独立しています。RDB(PostgreSQL)は共有されますがtest用databaseは別なので問題なく同じサーバーで動きますした。