capistranoを使ってみた

以前から使用してみたかったCapistranoを使ってみました。


最初に

要は、今まで本番環境へのデプロイアクションとして
・サービス停止
・ソース上げる(scp/ftp/rsync ...)
・バックアップ取得
・デプロイ(tar zxvf、chown/chmod...)
・サービス開始


っていう手順を踏んでいたのを
sshシンボリックリンクを駆使して、
コマンド1個でお手軽にできます。というツールです。
また、履歴管理もやっているので、戻し作業もすぐに出来るらしい(まだ未実施)。

インストール

必要なのは、開発(運用環境)側にssh/capistranoを準備。
本番環境へのインストールは不要です。
sshの話は省略してcapistranoの話です。

$ gem install capistrano
$ cd rails_app
$ capify .
[add] writing './Capfile'
[add] writing './config/deploy.rb'
[done] capified!

Capfileの中でconfig/deploy.rbをloadしています。
基本、専用タスクをconfig/deploy.rbに追記していく形になります。

config/deploy.rb

passenger / git を使うのを前提にした内容です。
デフォルトはmongrelを想定しているようなので
:deploy:restart / :deploy:start をoverrideします。


sudo絡みを解説すると、
コマンド実行には、runとrun_method(あとsudoもある)というのがあり
runはsshユーザで実行しますが、
:use_sudo を true(デフォルト)にした場合
run_methodではsudo実行になります。


基本sshユーザでのコマンド実行にしたかったため
:use_sudo を falseにしています。

set :application, "<app_name>"
set :scm, :git
set :repository,  "<repository_path>"
set :branch,      'master'
set :deploy_via,  :copy
set :deploy_to,   "<app_path>/#{application}"
set :use_sudo,    false

set :user,        '<ssh_user>'
set :password,    '<ssh_pass>'

role :web, "<web_server>"
role :app, "<app_server>"
role :db,  "<migration_server>", :primary => true

namespace :deploy do
  #deploy:restartタスク
  task :restart, :roles => :app do
    send(:run, "touch #{current_path}/tmp/restart.txt")
  end

  #deploy:startタスク
  task :start, :roles => :app do
    send(:sudo , "/etc/init.d/apache2 restart")
  end
end

各種コマンド

$ cap -h  # help
$ cap -H  # logn help
$ cap -T  # taskをlist rake -T みたいな感じ。

$ cap deploy:setup
deploy先にディレクトリ作成する。
デフォルトsudoを使う。sudoを使用したくなければ set :use_sudo, false としておく。
<作成ディレクトリ>
 app/
 app/releases
 app/shared
 app/shared/log
 app/shared/pids
 app/shared/system

$ cap deploy:check
deploy可能か(tarコマンド、ディレクトリ、ファイル書込権限のチェック)


$ cap deploy:cold
ソース更新、migration、deploy:startを実行。

$ cap deploy
ソース更新、migration無し。 & deploy:restartを実行。


一通り、触ってから見たのですが
下記、絵がdeployの処理について書かれていて分かりやすかったです。
http://www.capify.org/resources/default-execution-path/Capistrano%20Execution%20Path.jpg
Default Deployment Path - Capistrano


いざデプロイ

$ cap deploy:setup
$ cap deploy:cold / $ cap deploy

<ディレクトリ構成>
|-- current(releaseの最新に対してsymbolic link)
|-- release
      `--yyymmddHHMISS(日付毎にリリースプロジェクトを管理)
|-- shared(以下のディレクトリに対してrelease以下のプロジェクトからsymbolic link)
      |-- log
      |-- pid
      `--system

感想

かなり使えます。というかコレ必須です。
memcachedの再起動、apache mod_cahceの削除なども簡単に含めれたりします。
うっかりデプロイしちゃう危険性もあるので、そこは仕組みやルール決めが必要かなと。
あと、ディレクトリ構成変わるので、logrotate使ってる人は合わせてそちらも。

あとで調べる

・windowsでの実行
mongrelへのデプロイ
rails デプロイを後で見る(会社に置いてきたので)
・履歴(keep_releases)も設定変更できるようだが、ドキュメントにない

.gem/ruby/1.8/gems/capistrano-2.5.19/lib/capistrano/recipes
$ grep fetch deploy.rb 
_cset(:run_method)        { fetch(:use_sudo, true) ? :sudo : :run }
  deps = fetch(:dependencies, {})
  as = options.fetch(:as, fetch(:admin_runner, nil))
  via = fetch(:run_method, :sudo)
  args << options.merge(:as => fetch(:runner, "app"))
    run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
    if fetch(:normalize_asset_timestamps, true)
    rake = fetch(:rake, "rake")
    rails_env = fetch(:rails_env, "production")
    migrate_env = fetch(:migrate_env, "")
    migrate_target = fetch(:migrate_target, :latest)
    count = fetch(:keep_releases, 5).to_i
    other = fetch(:dependencies, {})
          dependencies.send(location).command(fetch(:gem_command, "gem")).or("`gem' command could not be found. Try setting :gem_command")

補足

The Ruby Toolbox Searchで見ると
capistranoよりmoonshineというツールの方がshareがあるようなので
そちらも気になります。