はじめてのCapistrano


Capistranoを使うととデプロイが簡単だという話を良く聞くけれど、
Capistranoを使うことが難しかったのでメモ。

Getting Started

インストール

$ gem install capistrano

実行する

設定ファイルを作成するコマンド

$ capify .

を実行すると、

[working_dir]/Capfile
[working_dir]/config
[working_dir]/config/deploy.rb

が作成される

タスクの基本

config/deploy.rbを空にして以下を記述する

config/deploy.rb
# localhost の ssh を許可しておくこと
task :list, :hosts => "localhost" do
    run "ls"
end

terminalで以下を実行する

$ cap list #=> localhostのファイル一覧が出力される

パスワードを問われるのはSSHで接続しているため

:hostをまとめる

デフォルトでは、全てのサーバー・全てのロールが実行される。
ロールを設定するのは局所的な動作を期待するため。

config/deploy.rb
# :hostsをまとめることができる
role :local, "localhost"

task :list do
    run "ls"
end

複数サーバーを設定する

config/deploy.rb
# 複数のサーバーに実行することができる
role :local, "localhost", "anotherhost"

task :list do
    run "ls"
end

複数ロールを設定する

config/deploy.rb
# 複数ロールを持つことができる
role :local, "localhost"
role :another, "anotherhost"

task :list, :roles => :local do
    run "ls"
end

task :list_another, :roles => :another do
    run "ls"
end

タスクの説明

config/deploy.rb
role :local, "localhost"

# コマンド一覧に表示される説明
desc "Echo the server's host name"
task :echo_hostname do
    run "echo `hostname`"
end
$ cap -vT #=> コマンド一覧

...
cap deploy:web:enable        # Makes the application web-accessible again.
cap echo_hostname            # Echo the server's host name
cap invoke                   # Invoke a single command on the remote servers.
...

コマンドを直接実行

cap invoke COMMAND="echo 'Hello World'" #=> Hello, Wrold

デプロイ設定

アプリケーション名を設定

config/deploy.rb
set :application => "myapplication"

リポジトリの設定

config/deploy.rb
# リポジトリの場所を指定する
set :repository, "ssh://localhost/var/git/myapplication.git"
# リポジトリの種類を指定する
set :scm, :git

デプロイ先の指定

config/deploy.rb
set :deploy_to, "/var/www/rails/"

role :app,  "localhost",                    # アプリケーションサーバー
role :web,  "localhost",                    # Webサーバー
role :db,   "localhost", :primary => true   # DBサーバー

DBはmaster/slaveがあればprimaryでコントロールできる
全て同じ場合は次のような書き方もできる。

config/deploy.rb
server "localhost", :app, :web, :db, :primary => true

実行ユーザーの設定

config/deploy.rb
set :user, "foo"

リポジトリユーザーの設定

config/deploy.rb
set :scm_username, "foo"

スーパーユーザー権限で実行の設定

config/deploy.rb
set :use_sudo, false #=> defaultではtrue

deployコマンド

cap deploy                # Deploys your project.
cap deploy:check          # Test deployment dependencies.
cap deploy:cleanup        # Clean up old releases.
cap deploy:cold           # Deploys and starts a `cold' application.
cap deploy:create_symlink # Updates the symlink to the most recently deployed...
cap deploy:migrate        # Run the migrate rake task.
cap deploy:migrations     # Deploy and run pending migrations.
cap deploy:pending        # Displays the commits since your last deploy.
cap deploy:pending:diff   # Displays the `diff' since your last deploy.
cap deploy:restart        # Blank task exists as a hook into which to install...
cap deploy:rollback       # Rolls back to a previous version and restarts.
cap deploy:rollback:code  # Rolls back to the previously deployed version.
cap deploy:setup          # Prepares one or more servers for deployment.
cap deploy:start          # Blank task exists as a hook into which to install...
cap deploy:stop           # Blank task exists as a hook into which to install...
cap deploy:symlink        # Deprecated API.
cap deploy:update         # Copies your project and updates the symlink.
cap deploy:update_code    # Copies your project to the remote servers.
cap deploy:upload         # Copy files to the currently deployed version.
cap deploy:web:disable    # Present a maintenance page to visitors.
cap deploy:web:enable     # Makes the application web-accessible again.
cap invoke                # Invoke a single command on the remote servers.
cap shell                 # Begin an interactive Capistrano session.

Namespace

Capistrano 2.x以降、全てのタスクはネームスペース化されており、モジュールとして分離できます。ここに処理をはさみ込むこともできます。

config/deploy.rb
# デプロイ時に rake resque:work を動かすgodスクリプトを呼ぶ
namespace :deploy do
  task :start, :roles => :app do
    run "god start resque-worker"
  end

  task :restart, :roles => :app do
    run "god restart resque-worker"
  end

  task :stop, :roles => :app do
    run "god stop resque-worker"
  end
end