Capistrano取扱説明書

# Capistranoとは
Rubyで記述されたDSLを用いて複数のリモート環境を操作するためのツールで、主にデプロイツールとして利用します。
コマンドを実行して、リモートのサーバーに最新のアプリケーションをデプロイし、サーバーを再起動する、といったことが可能です。

## インストール
gemパッケージとして提供されているので、`gem install`コマンドでインストールすることが出来ます。

```ruby
$ gem install capistrano
.
.
.
1 gem installed
```

## 必要ファイルの生成
`capify`コマンドを実行することで、デプロイに必要なファイルを生成することが出来ます。

```ruby
$ capify . #=> 「Capfile」と「config/deploy.rb」が生成される
```

＜Capfile＞
Capistrano本体である`cap`コマンド実行時に、タスクが記述されたファイルを読み込むために利用される。

＜config/deploy.rb＞
どういったサーバーにどうやってデプロイするか、といった実際のデプロイの流れを記述していきます。
一般的には、デプロイ処理をまとめたものを`レシピ`と言います。

## 設定
### set
Capistrano内部でオプションとなる項目の設定には`set`メソッドを使用します。

```ruby
# 第1引数にオプションのキーのシンボル、第2引数のキーに対する値
set :myname, 'sample123'
puts myname #=> "sample123"
```

デプロイをするには、「application」,「repository」,「scm」を設定する必要があります。

```ruby
# デプロイ対象となるアプリケーション名
set :application, 'sample_project'

# デプロイ対象のプロジェクトを管理しているリポジトリパスを指定
set :repository, 'https://github.com/sample/sample.git'

# 使用するバージョン管理システム
set :scm, :git
```

### role
デプロイするサーバーを用途別に分けてグルーピングする設定項目のこと。

```ruby
role :web, 'sample-web-server'
role :app, 'sample-app-server'
role :db, 'sample-db-primary-server', primary: true
role :db, 'sample-db-slave-server'

# set :applicationで指定したアプリケーション名を指定
set :deproy_to, "/var/www/#{application}"
```

## タスクとネームスペース
`タスク`とは、実際に行うデプロイ処理をまとめたもの。
`ネームスペース`とは、タスクの集まりに名前をつけたもの。
Capistranoはタスク単位でデプロイ処理を実行していき、`cap タスク名`で実行可能です。
※`desk`はタスクの説明文のことです。

```ruby
# cap :hello_capistrano
desc 'echo at remote server'
task :hello_capistrano do
  run 'echo "Hello, Capistrano!"'
end

# rolesオプションを指定することで、対象サーバーを指定
desc 'echo at remote server'
task :hello_capistrano, roles: [:web, :app] do
  run 'echo "Hello, Capistrano!"'
end

namespace :list do
  # cap list:ls
  desc 'execute ls'
  task :ls do
    run 'ls'
  end

  # cap list:ls_detail
  desc 'execute ls -l'
  task :ls_detail do
    run 'ls -l'
  end
end
```

## デプロイの流れ
Ruby on Railsのデプロイタスクをデフォルトで用意しています。タスク名は`deploy`で定義されています。

大まかな処理の流れとしては、、
①ソースコードの取得
②bundle install
③共有ファイルのシンボリックリンクの差し替え
④最新版ディレクトリのシンボリックリンク差し替え
⑤サーバー再起動

### Capistranoが利用するディレクトリ

| ディレクトリ | 意味 |
|:-:|:-:|
| releases  | デプロイされるプログラム一式が格納、デプロイごとに作成される  |
| current  | 現在稼働しているプログラム一式が格納  |
| shared  | アプリケーションが出力するログ・tmpディレクトリ・pidファイルが格納  |


## タスク実行時の出力内容の制御方法
`cap`コマンドを実行すると、各種ログが出力されます。このログは「重要度」に応じて出力されているので、`-v`オプションで表示内容を制御出来ます。
※段階的に出力レベルを引き上げるために`-vv`と`-vvv`が利用出来ます。

```ruby
desc 'echo at remote server'
task :hello_capistrano do
  run 'echo "Hello, Capistrano!"'
end

# -vオプションで表示内容を制御
$ cap -v hello_capistrano
```

## TransactionとRollback
Capistranoはトランザクション処理とロールバック処理の仕組みが備えられています。
複数ステップのデプロイ処理の中で問題が発生した際に、切り戻し処理を行うためのものです。

```ruby
desc 'transaction rollback test'
task :has_error, roles: :app do
  # 問題が起きる可能性のある箇所をトランザクション処理で囲む
  transaction do
　　 # ロールバック処理を記述
    on_rollback { run 'echo "has error"' }
    run 'command_does_not_exists "error?"'
  end
end
```

## フック処理


### フックの種類
タスク実行の前後などに、フック処理を指定することが可能です。
主に、`before`や`after`を使用します。

```ruby
desc 'before task'
task :before_task, roles: :app do
  run 'echo "this is before task"'
end

desc 'after task'
task :after_task, roles: :app do
  run 'echo "this is after task"'
end

desc 'main task'
task :main_task, roles: :app do
  run 'echo "this is main task"'
end

before 'main_task', 'before_task'
after 'main_task', 'after_task'
```

| 種類 | 説明 |
|:-:|:-:|
| before  | 指定したタスクの実行前  |
| after  | 指定したタスクの実行後  |
| start  | コマンドラインから指定されたタスクの実行前  |
| finish  | コマンドラインから指定されたタスクの実行後  |
| load  | レシピファイルの読み込み終了後  |
| exit  | 全てのタスク終了後  |

## パスワードの取り扱い
デプロイレシピに直接パスワードを記載するとセキュリティ的に問題なので、Capistranoではパスワード入力を求めるコマンドラインインターフェースを提供しています。
利用者からの入力を受けて、設定変数として利用します。

```ruby
set(:db_password) { Capistrano::CLI.password_prompt("DB password: ") }

desc 'connect to db client'
task :db_connect, roles: :db do
  run "db_connect --user='pruby' --password=#{db_password}"
end

cap db_connect -vv

  * executing 'db_connect'
DB password: # ここでパスワード入力が求められる
  * executing "db_connect --user='pruby' --password=password"
```

## sudoメソッド
Capistranoは通常SSHのログインユーザ権限でコマンドを実行します。時にroot権限が必要になる場合があります。その時に`sudo`メソッドを使用することで、root権限で実行可能になります。

```ruby
set
desc 'need sudo'
task :use_sudo_command, roles: :app do
  run "touch /tmp/cap_tmp"
  # root権限で実行している
  sudo 'rm /tmp/cap_tmp', as: 'tanaka.taro' # asオプションでどのユーザーで実行するか指定
```

## CaptureとStream
Capistranoには、サーバーで実行させたいコマンドの中には実行させた結果を取得してCapistrano側で処理したい場合や、サーバーの状態を観測するための処理も存在します。

### captureメソッド
`capture`メソッドとは、タスクの実行対象になるroleの最初に指定されたサーバーに対してコマンドを実行してその結果を返します。

```ruby
desc 'log size watch'
task :log_size_watcher do
  log_file = "#{deproy_to}/shared/log/development.log"
  ls_result = capture("ls -l #{log_file}")
  file_size = ls_result.squeeze.split(/ /)[4].to_i

  p "file size alert" if file_size > 100
end
```

### streamメソッド
`stream`メソッドは、複数サーバーに対して継続的なアウトプットを得たい時に利用します。
アプリケーションのログ観測などに利用します。

```ruby
desc 'log stream'
task :tail_log do
  stream("tail -f #{deproy_to}/shared/log/development.log")
end
```

## ストラテジー
アプリケーションをどのように本番環境に配信するかを、ストラテジーという仕組みで選択できるようになっています。

### ストラテジーの種類

| 種類 | 意味 |
|:-:|:-:|
| remote_cache  | 各サーバ側でアプリケーションのリポジトリを取得、フル取得→差分取得  |
| checkout  | デプロイごとにサーバーでリポジトリを丸ごと取得  |
| copy  | マシン上でファイルを取得し圧縮したものをサーバーに転送  |
| export  | デポロイごとにリポジトリを丸ごと取得  |
| unshared_remote_cache  | サーバー側でリポジトリを保持するディレクトリを指定し、remote_cache実行 |

## デプロイ環境の切り替え
デプロイする環境は、本番環境だけでなくステージング環境など異なる環境にデプロイする場合があります。
`config/deploy.rb`で、`capistrano/ext/multistage`をrequireすると利用可能になります。
※環境ごとに設定ファイルをそれぞれ設定しておく。

```ruby
set :stages, %w(production staging)
set :default_stage, :production

require 'capistrano/ext/multistage'
```

```config/deploy/production.rb
role :web, 'sample-web-server'
role :app, 'sample-app-server'
role :db, 'sample-db-primary-server', primary: true

set :deproy_to, "/var/www/#{application}"
```

```config/deploy/staging.rb
role :web, 'sample-staging-web-server'
role :app, 'sample-staging-app-server'
role :db, 'sample-staging-db-primary-server', primary: true

set :deproy_to, "/var/www_staging/#{application}"
```