DockerでRuby on RailsのCI環境を作ろうとした話
少し前にCIサーバーとして使っていたMac miniがお亡くなりになり、CIサーバーどうしようと考えていました。 Dockerを使いCI環境を作り、さくらのクラウドにあるステージング用のサーバーで動かせば良いのでは! と思い立ち土日に挑戦してみました。
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上で実行します。そこで必要になるものは、
- Jenkns
- RDB: PostgreSQL
- Ruby、Ruby on Rails, Capybara, 等をインストールするのに必要なライブラリー
- PhantomJS 等のコマンド
- a_JP.UTF-8 ローケール
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 ....
で止まってしまいます。仕方ないので、まずは OracleのJREを以下のような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は別なので問題なく同じサーバーで動きますした。