確実に忘れる上にドキュメントが全然見つからないCapistrano 3を VPS に Deploy する方法のメモ。
作業しながら書いてるのでホントに出来るかは書いてる本人もわかりません。
基本的には Railscast の[“Deploying to a VPS”][1]の設定とCapistrano 3の組み合わせです。
環境
Windows 7
Capistrano 3.1.0
rails 4.1.0
ruby 2.0.0p195 (2013-05-14) [i386-mingw32]
Postgresql
さくらの VPS (一番安いの)
git リポジトリ
VPS 上に git repository を作成しておいてそこにプロジェクトを push しときます。
場所は var/git-repos/#{site}.git。
Gemfile
# Use unicorn as the app server gem 'unicorn', group: :production # Use Capistrano for deployment gem 'capistrano', '~> 3.1' gem 'capistrano-rails', '~> 1.1' gem 'capistrano-rbenv', '~> 2.0'
Nginx
Nginxの設定ファイルをconfig/nginx.confに作成。※#{site}は適当に置き換える。
upstream unicorn_${site} {
server unix:/tmp/unicorn.${site}.sock fail_timeout=0;
}
server {
listen 80;
server_name ${site}.com;
access_log /var/log/nginx/${site}.com.access.log;
error_log /var/log/nginx/${site}.com.error.log info;
root /var/www/${site}.com/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn_${site};
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
Postgresql
chef でも使ってインストールしときましょう。
ローカルでもサーバー上でもuser: deployer, password: {none} な設定にしてdatabase.yml周りの変更をなくしてます。
Unicorn
Unicorn 用の設定を config/unicorn.rbに作成する。
root = "/var/www/${site}.com/current"
working_directory root
pid "#{root}/tmp/pids/unicorn.pid"
stderr_path "#{root}/log/unicorn.log"
stdout_path "#{root}/log/unicorn.log"
listen "/tmp/unicorn.${site}.sock"
worker_processes 2
timeout 180
こっちは起動・停止などの操作用
#!/bin/sh
set -e
# Feel free to change any of the following variables for your app:
TIMEOUT=${TIMEOUT-60}
APP_ROOT=/var/www/${site}.com/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
AS_USER=deployer
set -u
OLD_PIN="$PID.oldbin"
sig () {
test -s "$PID" && kill -$1 `cat $PID`
}
oldsig () {
test -s $OLD_PIN && kill -$1 `cat $OLD_PIN`
}
run () {
if [ "$(id -un)" = "$AS_USER" ]; then
eval $1
else
su -c "$1" - $AS_USER
fi
}
case "$1" in
start)
sig 0 && echo >&2 "Already running" && exit 0
run "$CMD"
;;
stop)
sig QUIT && exit 0
echo >&2 "Not running"
;;
force-stop)
sig TERM && exit 0
echo >&2 "Not running"
;;
restart|reload)
sig HUP && echo reloaded OK && exit 0
echo >&2 "Couldn't reload, starting '$CMD' instead"
run "$CMD"
;;
upgrade)
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
then
n=$TIMEOUT
while test -s $OLD_PIN && test $n -ge 0
do
printf '.' && sleep 1 && n=$(( $n - 1 ))
done
echo
if test $n -lt 0 && test -s $OLD_PIN
then
echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds"
exit 1
fi
exit 0
fi
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
run "$CMD"
;;
reopen-logs)
sig USR1
;;
*)
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
exit 1
;;
esacCapistrano 初期化
$ bundle exec cap install
で以下のファイルが生成される。
├── Capfile
├── config
│ ├── deploy
│ │ ├── production.rb
│ │ └── staging.rb
│ └── deploy.rb
└── lib
└── capistrano
└── tasks
Capfile の設定
rbenvを使うかrvmを使うかなどで適宜変更。うちは system インストールしたrbenvを使うのでこんな感じ。ruby のバージョンが若干古めなのは Windows の Railsinstaller に合わせてるので。
# Load DSL and Setup Up Stages
require 'capistrano/setup'
# Includes default deployment tasks
require 'capistrano/deploy'
# Includes tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
# https://github.com/capistrano/rvm
# https://github.com/capistrano/rbenv
# https://github.com/capistrano/chruby
# https://github.com/capistrano/bundler
# https://github.com/capistrano/rails
#
# require 'capistrano/rvm'
require 'capistrano/rbenv'
# require 'capistrano/chruby'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
# config/deploy.rb
set :rbenv_type, :system # or :user, depends on your rbenv setup
set :rbenv_ruby, '2.0.0-p195'
set :rbenv_path, '/usr/local/rbenv'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
set :rbenv_roles, :all # default value
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }deploy.rb の設定
Capistrano の設定。2 に比べてリンクするディレクトリの設定とかをやってくれるようになってるので楽です。それに関するドキュメントが少なくてつらい思いをすることを除けばね!
# config valid only for Capistrano 3.1
lock '3.1.0'
set :application, '${site}'
set :repo_url, 'ssh://deployer@${site}.com:10022/var/git-repos/#{site}.git'
# Default branch is :master
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }
# Default deploy_to directory is /var/www/my_app
set :deploy_to, '/var/www/${site}'
# Default value for :scm is :git
# set :scm, :git
# Default value for :format is :pretty
# set :format, :pretty
# Default value for :log_level is :debug
# set :log_level, :debug
# Default value for :pty is false
# set :pty, true
# Default value for :linked_files is []
# set :linked_files, %w{config/database.yml}
# Default value for linked_dirs is []
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
# Default value for keep_releases is 5
# set :keep_releases, 5
namespace :deploy do
%w(start stop restart).each do |command|
desc '#{command} unicorn server'
task fetch(:command) do
on roles(:app), in: :sequence, wait: 5 do
run "/etc/init.d/unicorn_#{application} #{command}"
end
end
end
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
# Here we can do anything such as:
# within release_path do
# execute :rake, 'cache:clear'
# end
end
end
end