Less is Best

rubyが好き。技術の話とスタートアップに興味があります。

Unicorn+RailsアプリをDockerコンテナで動かす

Unicorn+Rails入門にでUnicorn+Railsなアプリ(yss44/unicorn_sample)を作って、起動させてみましたが、今度はそれをDockerコンテナの中で動かしてみたいと思います。そのために、Railsを動かすためにカスタマイズしたDockerイメージとUnicorn+Railsアプリを動かすコンテナを作ってみました。

さてさて、Dockerコンテナのご紹介

Docker_rails_base

こちらは

  • sshd
  • supervisord
  • rbenv ruby-2.0.0p-353
  • nvm node.js v0.10.24

の入っているDockerコンテナ。Railsを動かすための実行環境を整えてあげているイメージです。こちらのイメージを継承して、実際のアプリケーションの配置を行なうためのイメージを作る戦略を取りました。

Docker_rails_unicorn

こちらでは、githubからソースを取って来て、Rails+Unicornのアプリケーションをコンテナ内で起動させるコンテナになります。プロダクション環境で起動させる仕様にしています。

Dockerfileはこんな感じになっております。

Docker-Rails-Base

Dockerfile

# DOCKER-RAILS
#
# VERSION       1

FROM centos

MAINTAINER yoshiso

RUN yum -y update

#Dev tools for all Docker
RUN yum -y install git vim
RUN yum -y install passwd openssh openssh-server openssh-clients sudo

########################################## sshd ##############################################

# create user
RUN useradd yoshiso
RUN passwd -f -u yoshiso
RUN mkdir -p /home/yoshiso/.ssh;chown yoshiso /home/yoshiso/.ssh; chmod 700 /home/yoshiso/.ssh
ADD sshd/authorized_keys /home/yoshiso/.ssh/authorized_keys
RUN chown yoshiso /home/yoshiso/.ssh/authorized_keys;chmod 600 /home/yoshiso/.ssh/authorized_keys
# setup sudoers
RUN echo "yoshiso ALL=(ALL) ALL" >> /etc/sudoers.d/yoshiso
# setup sshd
ADD sshd/sshd_config /etc/ssh/sshd_config
RUN /etc/init.d/sshd start;/etc/init.d/sshd stop

#######################################  Supervisord  ########################################

RUN wget http://peak.telecommunity.com/dist/ez_setup.py;python ez_setup.py;easy_install distribute;
RUN wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py;python get-pip.py;
RUN pip install supervisor

ADD supervisor/supervisord.conf /etc/supervisord.conf


#######################################   Ruby and Node Runtime  ########################################
# Installing Rails Runtime, Ruby and Node.js
RUN yum -y install gcc make zlib zlib-devel readline readline-devel openssl openssl-devel curl curl-devel
ADD install.sh install.sh
RUN chmod +x install.sh; ./install.sh;

RUN usermod -G yoshiso,rbenv,nvm yoshiso


###################################### Docker config #########################################


# expose for sshd

EXPOSE 2222

CMD ["/usr/bin/supervisord"]

Rubyとnode.jsのインストールスクリプト。これ書くのに無駄に苦労しました。rbenv,nvmをシステムワイドで利用可能かつ、sshログインするユーザーがgemをインストールできるように。 結局、rbenv,nvmを利用させたいユーザー(gemをインストールしたいユーザー)はrbenv,nvmグループに追加させる仕組みにしてみた。

install.sh

#!/bin/bash
#Install Ruby by rubyenv

if [ ! -d /usr/local/rbenv ];then
    cd /usr/local
    git clone git://github.com/sstephenson/rbenv.git rbenv
    mkdir rbenv/shims rbenv/versions rbenv/plugins
    git clone git://github.com/sstephenson/ruby-build.git /usr/local/rbenv/plugins/ruby-build

    # Setup rbenv for all user
    echo 'export RBENV_ROOT="/usr/local/rbenv"' >> /etc/profile.d/rbenv.sh
    echo 'PATH=/usr/local/rbenv/bin:$PATH' >> /etc/profile.d/rbenv.sh
    echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh
    source /etc/profile.d/rbenv.sh

    # Install ruby
    rbenv install 2.0.0-p353
    rbenv rehash
    rbenv global 2.0.0-p353  # default ruby version

    #rbenv(add user to rbenv group if you want to use rbenv)
    useradd rbenv
    chown -R rbenv:rbenv rbenv
    chmod -R 775 rbenv

    # install withou ri,rdoc
    echo 'install: --no-ri --no-rdoc' >> /etc/.gemrc
    echo 'update: --no-ri --no-rdoc' >> /etc/.gemrc
    echo 'install: --no-ri --no-rdoc' >> /.gemrc
    echo 'update: --no-ri --no-rdoc' >> /.gemrc

    # install bundler
    gem install bundler
fi

#Install Node.js for Rails javascript runtime

if [ ! -d /usr/local/nvm ];then
    # install nvm
    git clone https://github.com/creationix/nvm.git /usr/local/nvm
    source /usr/local/nvm/nvm.sh

    # nvm(add user to nvm group if you want to use nvm)
    useradd nvm
    chown -R nvm:nvm /usr/local/nvm
    chmod -R 755 /usr/local/nvm
    nvm install 0.10.24

    # Setup rbenv for all user
    echo 'source /usr/local/nvm/nvm.sh' >> /etc/profile.d/nvm.sh
    echo 'nvm use v0.10.24' >> /etc/profile.d/nvm.sh
fi

Docker-Rails-Unicorn

ソースコードはこちら@github

Dockerfile

# DOCKER-RAILS-UNICORN
#
# VERSION       1

FROM yoshiso/rails_base

MAINTAINER yoshiso


ADD supervisor/supervisord.conf /etc/supervisord.conf


#######################################   Rails  #############################################

ENV PATH /usr/local/rbenv/bin:$PATH
ENV RAILS_ENV production

# Git pull latest Rails App
RUN mkdir /var/www; cd /var/www;
RUN git clone https://github.com/yss44/unicorn_sample.git /var/www/app;

# Resolve dependencies
RUN yum -y install sqlite-devel
RUN source /etc/profile.d/rbenv.sh;gem install sqlite3 -v '1.3.8' # Have to be installed
RUN source /etc/profile.d/rbenv.sh;cd /var/www/app;bundle install -j4;

# Setup rails(db:migrate,assets precompile)
RUN source /etc/profile.d/rbenv.sh;source /etc/profile.d/nvm.sh;cd /var/www/app;RAILS_ENV=production bundle exec rake deploy:prepare;

# Add execution file used by supervisor
ADD rails/start.sh rails_start.sh
RUN chmod +x rails_start.sh

###################################### Docker config #########################################

# Environment valiables
ENV WEB_CONCURRENCY 4
ENV RAILS_ENV production

# expose for sshd,rails

EXPOSE 2222 3000

CMD ["/usr/bin/supervisord"]

Railsの起動スクリプトはこちら

rails/start.sh

#!/bin/bash

source /etc/profile.d/nvm.sh;
cd /var/www/app;
/usr/local/rbenv/shims/bundle exec unicorn_rails -c /var/www/app/config/unicorn.rb -E production

supervisor/supervisord.conf

[supervisord]
nodaemon=true

[program:sshd]
command=/usr/sbin/sshd -D

[program:rails_app]
command=/rails_start.sh

RUNを実行する時はどうやらrootユーザー権限で実行しているようですが、 /etc/profileを読み込みに行っていない状態でコマンドの実行を行なっている ようで、そこではまりました。しかも、各RUN毎に、いちいち初期化されるので(システム的に仕方ないですが)rbenvとかをDockerfileからコンテナ生成する際にどう実行させれば良いかかなり悩みました。今の所、source /etc/profile.d/rbenv.sh等をRUNコマンドの最初に実行してrbenv,nvmを使えるようにしてから実行するというとても汚いコードになってしまいました。解決策を持っている方いらしたら教えて頂きたいです。

とまあ問題はありましたが、これでUnicorn+RailsなアプリケーションをDockerコンテナを使って起動することに成功しました! デプロイする際には、このイメージをサーバーでdocker pullしてきてdocker runするだけでデプロイが完了するようになります!あとは、Nginxをフロントにおいてあげるだけです。これは便利!正直デプロイツールのCapistranoとかいりませんね!

とか言ってたけど正直自動化する仕組みが無いと面倒くさくてやってられんって感じ。静的ファイル配信とか考えるとはわわわわ。

--

実際に使ってみたい方は、ソースコードのままだとsshdまわりで動きません。(公開鍵認証設定のssh接続にしているため) ですので、公開鍵認証用の設定を施す必要があります。

yss44/docker_ssh

MacからSSH接続可能なDockerコンテナを作る。

こちらを参考にsshdの設定を行なっていただければ、動かすことは可能ですので楽しんでみてください。