Capistrano3でrailsをdeployしてみる

CapistranoはオープンソースのRuby製ソフトウェアデプロイメントツールです。

![CapistranoLogo.png](https://qiita-image-store.s3.amazonaws.com/0/11493/e38f5011-d01c-2035-7c52-527b3e223477.png "CapistranoLogo.png")

複数のサーバへのソフトウェアのデプロイメントを自動化する事ができます。
railsを対象によく用いられますが、railsなどのフレームワークや言語に限らずデプロイする事ができます。  
現在最新版は3.0.1となります。(2014/1/12現在)  
なおCapistranoは2から3への変更時にパラメータの持ち方などが変わり互換性がなくなっています。今回は3以降の記述で行います。  
[公式ページ](http://capistranorb.com/)

|今回の環境   |
|---------|
|CentOS6.4  |
|Ruby 2.1     |
|rbenv          |

###1.インストール
gemを使ってcapistranoをインストールします。 rootでない場合は```sudo```も付けてください。  
railsじゃない場合はcapistrano-railsは必要ありません。

```
gem install capistrano
gem install capistrano-rails
gem install capistrano-rbenv #またはcapistrano-rvm
```

bundlerを使っている場合は下記の記述をGemfileに追記してbundler installを実行してください。

```
gem 'capistrano', '~> 3.0.1'
gem 'capistrano-rails'
gem 'capistrano-bundler'
```

###2.設定ファイル作成
設定ファイルを作成します。railsのルートディレクトリで下記コマンドを実行してください。 

```
cap install
```

これで下記のファイルが作成されます。

```
railsルート
├─	Capfile
├─  config
│	├─	deploy
│	│	├─production.rb
│	│	└─staging.rb
│	└─deploy.rb
└─	lib
	└─capistrano
		└─tasks
```

###3.Capfile記述
まずCapfileを記述します。  
初期ではコメントアウトがあるので必要なものをコメントアウトから外します。

```ruby:Capfile
# 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/tree/master/assets
#   https://github.com/capistrano/rails/tree/master/migrations
#
# require 'capistrano/rvm' #rvmならこちらを外す
require 'capistrano/rbenv' #rbenvならこちらを外す
set :rbenv_type, :system # or :system, depends on your rbenv setup
set :rbenv_ruby, '2.1.0' #rubyのバージョンを指定
# require 'capistrano/chruby'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
```
###4.deploy/{環境}.rb記述
deployフォルダ配下にproduction.rbやstagingなどが初期ではあります。  
追加したければdevelopment.rbなどを追加します。

```ruby:development.rb
set :stage, :production #環境名
#各サーバの役割を記述
role :app, %w{deploy@example.com} #アプリケーションサーバ
role :web, %w{deploy@example.com} #webサーバ
role :db,  %w{deploy@example.com} #DBサーバ
#サーバ情報記述
server 'example.com', #サーバ名
user: 'deploy', #実行ユーザ
roles: %w{web app db}, # サーバの役割
ssh_options: {
	keys: %w(~/.ssh/xxxxx/private_key),
	auth_methods: %w(publickey), # 認証方法 passwordも可能
	#password: 'xxxxx' #password指定
}
```

###4.外部ファイルにタスクを記述する
deploy.rbの外部ファイルにタスクを記述する事ができます。  
lib/capistrano/tasks配下にXXXX.capファイルを作成します。
今回はunicornの起動タスクunicorn.rbとして記述します。

```ruby:unicorn.rb
namespace :unicorn do
  task :environment do
    set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid"
    set :unicorn_config, "#{current_path}/config/unicorn/#{fetch(:rails_env)}/unicorn.rb"
  end

  def start_unicorn
    within current_path do
      execute :bundle, :exec, :unicorn_rails, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -p 8080 -D"
    end
  end

  def stop_unicorn
    execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
  end

  def reload_unicorn
    execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})"
  end

  def force_stop_unicorn
    execute :kill, "$(< #{fetch(:unicorn_pid)})"
  end

  desc "Start unicorn server"
  task :start => :environment do
    on roles(:app) do
      start_unicorn
    end
  end

  desc "Stop unicorn server gracefully"
  task :stop => :environment do
    on roles(:app) do
      stop_unicorn
    end
  end

  desc "Restart unicorn server gracefully"
  task :restart => :environment do
    on roles(:app) do
      if test("[ -f #{fetch(:unicorn_pid)} ]")
        reload_unicorn
      else
        start_unicorn
      end
    end
  end

  desc "Stop unicorn server immediately"
  task :force_stop => :environment do
    on roles(:app) do
      force_stop_unicorn
    end
  end
end
```

##5.deploy.rb記述
deploy.rbにデプロイ時のタスクを記述していきます。  
ここでは各環境共通の処理、変数を記述します。
```set :対象変数```で変数に値を設定します。この値は```fetch :対象変数```で使用する事ができます。

```ruby:deploy.rb
#アプリケーション名
set :application,'test'
#レポジトリURL
set :repo_url, 'git@bitbucket.org:xxxxxx/test.git'
#対象ブランチ masterに固定
set :branch, 'master'
#デプロイ先ディレクトリ フルパスで指定
set :deploy_to, '/var/www/test'
#バージョン管理方法 subverion, git, mercurial, cvs, bzrなど
set :scm, :git
#情報レベル info or debug
set :log_level, :debug
#sudoに必要 これをtrueにするとssh -tで実行される
set :pty, true
#sharedに入るものを指定
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets bundle public/system public/assets}
#capistrano用bundleするのに必要
set :default_env, { path: "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH" }
#5回分のreleasesを保持する
set :keep_releases, 5 

#タスク定義
namespace :deploy do #タスクnamespace
    #desc 'タスク説明'
    #task :restart do #タスク定義 
    	#ここにタスク処理内容を記述
    #end
  #after :finishing, 'deploy:cleanup' #task実行タイミングを指定できます。詳細は下記
  #http://capistranorb.com/documentation/getting-started/flow/
    #サンプルにunicorn再起動タスク
    desc 'Restart application'
    task :restart do
      invoke 'unicorn:restart' #lib/capustrano/tasks/unicorn.cap内処理を実行
    end
  after :finishing, 'deploy:cleanup'
end
```

###6.実行
実行します。

```
cap <対象環境名> deploy
```
これで対象サーバに対してデプロイメントが実行されます。
Capistranoは実行すると下記のような配置がされます。

```
railsルート
├─current #releases内最新のシンボリックリンク
├─	releases #配下に現在時刻に基づく名前のサブディレクトリが作成され最新コードがチェックアウトされる
└─	shared #リリース間で共用するファイルを置いておく
```