Capistrano3を使ってデプロイを自動化した

DMM Samplerを作成してから、バージョンアップに向けてちょこちょこ作業していました。
そして3つの事を達成。

  1. DMMアフィリエイトプログラムの審査に合格
  2. Webページにタグリンクを設置
  3. Capistrano3を用いてデプロイを自動化

一つ目はどうでもいいですね。ようやくAPIが使えるようになったと思ったら、API経由ではランダムで商品を検索出来ないため、あえなく利用は断念しました。

二つ目も小さい改良ですが、使ってもらえると嬉しいです。

三つ目が本題です。
最近Railsをきちんと学ぼうと思い、書籍を購入しました。

RailsによるアジャイルWebアプリケーション開発 第4版

RailsによるアジャイルWebアプリケーション開発 第4版

その中で「デプロイメントの自動化」について触れていました。
そこで今回DMM Samplerについて、晴れてデプロイの自動化をしたわけです。

Capistrano3の導入

本の中ではCapistrano2を利用していましたが、今回は最新版の3を利用しました。
このCapistranoというツールが、デプロイを自動的に行います。

今回の構成は、コマンドを叩くとリモートサーバに対して、

  1. Webサーバのリスタート
  2. gitリポジトリから最新モジュールを取得
  3. gemパッケージをインストール

といった作業を行うようCapistranoを設定しました。

サーバ構成

今回デプロイ対象となるサーバは以下のような構成です。

  • Rails3.2.3
  • ruby1.9.3(RVM利用)
  • Passenger + Apache2
  • アプリケーションディレクトリ:/var/www/sampler

Gemの追加

CapistranoはGemで提供されているため、プロジェクトのGemfileへ追記してインストールするだけでオッケーです。
ただし今回はrvmを利用し、かつbundlerによるGemインストールも行うため以下のように3つのgemを追記しました。

#Gemfile
gem 'capistrano'
gem 'capistrano-rvm'
gem 'capistrano-bundler'

あとはbundle install。

初期ファイルの作成

導入が終わったら、capistranoの初期ファイルを作成します。

#railsプロジェクトのルートディレクトリで実行する。
cap install

これにより、./Capfileと./config配下に各種設定ファイル・ディレクトリが作成されます。

デプロイ設定

作成された設定ファイルの内容を編集します。

まずはCapfileから。Capfileはデプロイコマンド実行前に関連ライブラリを読み込むといった役割を果たしているようです。

#Capfile

require 'capistrano/setup'
require 'capistrano/rvm'
require 'capistrano/bundler'
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }


次は./config/deploy/production.rbを設定します。
capistranoはデプロイ環境ごとにサーバ名などの情報を作成しておくことができます。
これにより、デプロイコマンド実行時にサーバ名を指定することで、対象のデプロイサーバ情報を取得します。

#./config/deploy/production.rb

set :stage, :production
role :app, %w{user@server}
role :web, %w{user@server}
role :db,  %w{user@server}
server 'server', user: 'user', roles: %w{web app}, my_property: :my_value

正直このファイルについてはあまり調べていませんが・・・
アプリケーションやDBなどを異なるサーバで担当している場合には、roleに名前とサーバ名を紐付けておくと便利です。
次に設定するdeploy.rb内で、「appだけ、dbだけに対して処理を行う」といったことが可能になります。


最後に./config/deploy.rbです。こいつがデプロイ自動化の本体になります。

#./config/deploy.rb

set :repo_url, 'git@github.com:quotto/Sampler.git'
set :deploy_to, '/var/www/sampler'
set :scm, :git
set :rvm_ruby_version, "ruby-1.9.3-p448"

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

repo_urlに取得元のリポジトリ、deploy_toにリポジトリのクローン先を指定します。
rvm_ruby_versionを指定することで、デプロイ先サーバのrvmバージョンを指定します。指定文字列はサーバに設定されているものを利用します。


また、デプロイ実施前の処理としてサーバの再起動を設定しました。
先のproduction.rb内で設定した「app」サーバに対してのみ処理を行います。
実行デプロイコマンド(今回はcap production deploy)に合致したnamespace内のスクリプトが実行される仕組みのようです。

デプロイ実行!

ここまでで設定は完了。あとはコマンドを実行します。

cap production deploy

./config/deploy/production.rbで設定した内容を読み込み、./config/deploy.rbのnamespace :deploy内の処理が実行されます。
これだけでリモートサーバにてWebサーバ再起動、デプロイ、Gemインストールの処理が行われます。

なお、Capistranoを利用すると./currentディレクトリの配下にデプロイされます。
また、それまでデプロイしたプロジェクトは./release配下に格納されます。
(./currentも実は./release配下にある最新プロジェクトのシンボリックリンクだったりします。)

以上でデプロイ自動化が完成しました。
まぁcapistrano-bundlerなどの存在を知らずに4、5時間四苦八苦したのですが・・・