rbenvの環境にRailsアプリをCapistranoでデプロイする

レンタルサーバの引っ越しついでにrubyRailsのバージョンを上げて、再度Capistranoによるデプロイ環境を構築しました。

構成

サーバ
  • CentOS 6.3
  • ruby 2.1.2(rbenvで導入)
  • Rails 4.0
  • Apache2 + Passenger4.0
クライアント(デプロイ環境)

ruby(rbenv)の導入

rbenvを使ってrubyをインストールします。

# rbenvのインストール
$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
$ mkdir -p ~/.rbenv/plugins
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

続いて.bash_profileに環境変数を設定。

#~/.bash_profile

export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

opensslのライブラリをインストール。

$ sudo yum install openssl-devel

rubyのインストール。

# ruby本体
$ rbenv install 2.1.2
…
# bundler
$ rbenv exec gem install bundler

その他、bundle install時に必要となるシステムライブラリをインストール。
(本当は散々デプロイ失敗しながら地道に1つずつ入れました・・・)

$ sudo yum install zlib
$ sudo yum install readline
$ sudo yum install libxml2
$ sudo yum install libxslt-devel
$ sudo yum install libxml-devel
$ sudo yum install sqlite-devel
$ sudo yum install curl-devel
$ sudo yum install httpd-devel
$ sudo yum install apr-devel
$ sudo yum install apr-util-devel

たぶんこのくらいだった。

Rails開発環境の構築(rbenvでRuby導入からBundler、Rails導入まで)(Macport編) - Qiita

capistrano構築

まずはGemfileから。

#Gemfile
gem 'rails', '4.0.0'   #Rails4を指定
…
group :development do     
  gem 'capistrano'
  gem 'capistrano-rbenv'   #デプロイ先のrbenv環境をベースとするため 
  gem 'capistrano-bundler'   #デプロイ先でbundle installを実施するため
  gem 'capistrano-rails'   #アセットパイプラインのプリコンパイル用
end

そしてインストール。

$ bundle install

次にCapfileで利用するモジュールなど指定。

#Capifile

require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'

Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

次にdeploy.rb編集

#config/deploy.rb

set :application, 'myapp'
set :ssh_options,:port => '1234'  #sshのポート指定(デフォルト以外の場合)
set :repo_url, 'git@github.com:user/myapp.git'
set :deploy_to, '/var/www/project/myapp'
set :scm, :git

set :rbenv_ruby, '2.1.2'    #サーバで利用するrubyのバージョンを指定
set :default_env, { 
     rbenv_root: "#{fetch(:rbenv_path)}",
     path: "#{fetch(:rbenv_path)}/shims:#{fetch(:rbenv_path)}/bin:$PATH"}
set :bundle_without, [:development]   #Gemfile内のdevelopmentグループ以外を対象にする

namespace :deploy do
  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      execute :touch, "#{fetch :deploy_to}/current//tmp/restart.txt"
    end
  end
end

さらにデプロイ対象の設定を行うproduction.rbを編集。

#config/deploy/production.rb

role :app, %w{user@www.example.com}
role :web, %w{user@www.example.com}
role :db,  %w{user@www.example.com}

server 'www.example.com', user: 'user', roles: %w{web app}, my_property: :my_value

いざデプロイ!!

bundle exec cap production deploy

このデプロイでアプリケーションを配置し、bundle installを実行、アセットパイプライン上のファイルがプリコンパイルされます。
ちなみに、

  • Bundlerによるgemのインストール先はデフォルトで$RailsRoot/shared/bundle。
  • プリコンパイル先はデフォルトで$RailsRoot/current/public/assets
    ※public/assetsは$RailsRoot/shared/public/assetsへのシンボリックリンク

となります。

GitHub - capistrano/bundler: Bundler support for Capistrano 3.x
CapistranoとBundlerの連携 - Develop with pleasure!
capistranoでbundle installする - 昼メシ物語
GitHub - capistrano/bundler: Bundler support for Capistrano 3.x
Capistranoでassets:precompileを自動化 - Qiita

Passenger導入

デプロイが完了したら本番サーバにpassengerを導入します。

$ $RailsRoot/shared/bundle/ruby/2.1.0/gems/passenger-4.0.45/bin/passenger-install-apache2-module

apacheの設定ファイルを編集。

#/etc/host/conf/httpd.conf

#モジュールの追加
LoadModule passenger_module /var/www/project/myapp/shared/bundle/ruby/2.1.0/gems/passenger-4.0.45/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /var/www/project/kanken/shared/bundle/ruby/2.1.0/gems/passenger-4.0.45
PassengerDefaultRuby /home/yamada/.rbenv/versions/2.1.2/bin/ruby
</IfModule>
…
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.example.com   #アプリケーションのURL
DocumentRoot /var/www/project/myapp/current/public
RackEnv production   #本番環境を指定
    <Directory /var/www/project/myapp/current/public>
         AllowOverride all
         Options -MultiViews
     </Directory>
</VirtualHost>

最後にhttpd再起動。
※2回目以降のデプロイには不要

$ sudo service httpd restart

まとめ

ざっくりとですがこんな感じです。
ポイントとしては

特に最後のアセットパイプラインのプリコンパイルについては苦戦したので次回詳しく振り返ってみます。


capistranoは便利だけど、初回のデプロイはデプロイ先でrbenv導入=>デプロイ=>passenger導入と、rbenvとpassengerはどうしても手動でやらなければならないのがちょっと大変だなーと思いました。