---
categories: "Capistrano"
comments: true
date: "2014-04-12T00:00:00+09:00"
title: "Capistrano3を最後にもう一度だけ懇切丁寧にまとめてみる"
---
いろいろエントリーを上げながら苦しんでいたCapistranoだが、ようやっとそこそこ落ち着いてきた気がするのでそろそろ完結編といく。Capistranoの基本とかはすでに[こちら](http://chroju89.hatenablog.jp/entry/2014/02/20/000348)のエントリーで書いたので、今回は各設定ファイルの書き方とか、その他ハマったポイントを中心に。
## 今回作成したファイル
以下4ファイルを作成した。
* Capfile
* config/deploy.rb
* config/deploy/staging.rb
* lib/capistrano/tasks/unicorn.cap
基本的にCapistranoを使う場合「必須」なのは上2つのファイル。`deploy/hoge.rb`も確実に必要にはなるが、デプロイ先の環境が本番なのかステージングなのかでproduction.rbとstaging.rbを使い分けることになる。もちろん、ステージング環境を用意していない場合はstaging.rbは不要。また4つ目のファイルだが、自分の場合はunicornをデプロイ先で使っているので、デプロイ後にunicornを再起動する目的で独自タスクを作成している。説明が遅れたが、今回デプロイ先となる環境は大雑把に以下の通り。
* Vagrant 1.4.3
* CentOS 6.4
* Postgresql 9.1
* Ruby 1.9.3(rbenv)
* Nginx + unicorn
* 位置付けはステージング環境
## Capfile
ここはだいたい環境を問わず同じになってくる箇所。まず`capistrano/setup`と`capistrano/deploy`は`require`が必須。RailsをCapistranoで扱う場合は、`capistrano/bundler`から`capistrano/rails/assets`までも必須となる。rbenvを使っている場合は`capistrano/rbenv`が必要。rbenvをどこにインストールしたのかにより、`set :rbenv_type`を指定する。あとはデプロイするアプリケーションで使うRubyのバージョンも指定してやる。rvmを使う場合も似たような`capistrano/rvm`を使うみたいだが、そちらはよくわからんので割愛。
で、ここまでがrequireということなので、デプロイ元サーバーにGemfile書いてインストールしておくことを忘れずに。
```
group :development do
gem 'capistrano', '~> 3.1.0', :require => false
gem 'capistrano-rails', '~> 1.0.0', :require => false
gem 'capistrano-rbenv', '~> 2.0', :require => false
gem 'capistrano-bundler', '~> 1.1.2', :require => false
end
```
最終行は独自カスタムタスクを読み込むための行。デフォルトで入っているのでそのままにしておけばよい。先のunicorn.capのように、何か独自タスクを作った場合はこのパスに入れれば読み込むよーということでもある。
なお、以前書いたエントリーでは`capistrano3/unicorn`も`require`していたのだが、これは撤回した。詳細はunicorn.capについて説明するときに後述。
## staging.rb
ステージング環境、というかデプロイ先環境の設定を書く。vagrantを使う場合はだいたいこれと同じように書いておけば通るんじゃないかと思う。Vagrantはデフォルトではvagrantユーザーによるsshが可能になっているので、それをそのまま使わせてもらっている。何か他のユーザーで入りたい場合などは頑張るしかない。
一点だけ注意すべきは、`RAILS_ENV`がstagingに設定されるということ。Capistrano3では`cap install`を叩くとデフォルトでstaging.rbとproduction.rbが作られ、`RAILS_ENV`もこのファイル名に倣うことになるのだが、Railsの動作環境は通常test, development, productionの3種類であり、stagingは存在していない。従ってこのままデプロイを始めてもうまくはいかない。面倒であればstaging.rbは使わず、production.rbだけを使っていてもいいかもしれない。
staging.rbを使う場合は、Rails側で環境の準備が必要になる。やることは大きく3つ。
### 1. database.ymlにstagingを作成する
`rake db:migrate`などのDB系のコマンドはi`RAILS_ENV`を指定して実行される。ここで指定された`RAILS_ENV`をdatabase.ymlに見に行くので、設定を入れておく必要がある。ステージング環境の本来の意味を考えると、production用の記述をそのままコピーするだけで良いはず。
### 2. config/environments/staging.rbを作成する
動作環境設定ファイルとして、デフォルトではproduction.rbとdevelopment.rbだけが用意されているので、これもproduction.rbをコピーしてstaging.rbを作る。
### 3. Gemfileにgroup :stagingを作成する
これは`RAILS_ENV`と直結するわけではないが、GemfileのグループもRails環境ごとに作られているのでstagingを設けてやった方が良さそう。これもここまでと同様の話で、`group :staging, :production do`としてやるだけで良い。
* 参考:[railsでstaging環境を作る - CubicLouve](http://spring-mt.tumblr.com/post/33209507135/rails-staging)
## deploy.rb
いよいよデプロイ用の設定。面倒なので説明は省くが、だいたいはコメント読めば設定できるはず。
`linked_files`と`linked_dirs`は[前回のエントリー](http://chroju89.hatenablog.jp/entry/2014/04/06/191336)で書いた通り、shared配下に置いているファイルやフォルダのうち、currentに必要となるものを指定することでシンボリックリンクを張ってくれるというものなのだが、ではshared配下にこれらファイルやフォルダはいつ作られるのか?というのがかねてから疑問だった。
結論を言えば、`linked_files`は勝手には作成されない。というより、ここに指定したファイルがshared下に存在しない場合、Capistranoはデプロイ時にエラーを吐いてくる。正確に言えば`deploy:check:linked_files`というタスクがあり、ここで存在確認を行っている([参照](https://github.com/capistrano/capistrano/blob/master/lib/capistrano/tasks/deploy.rake))。したがってこのタスクが投げられる前にファイルは別でアップロードしなくてはならない。ここではdetabase.ymlを指定しているので、アップロードタスクを独自で組み込んでいる。詳細は後述。
一方の`linked_dirs`は、shared配下に存在しない場合は`deploy:check:make_linked_dirs`で空っぽのフォルダとして作成してくれる。逆に言えば、元々ファイルが入っているようなフォルダをここで指定することはあまりないということ。例えばbundleなり、logやtmpなり、アプリが動作する中で必要とされるフォルダ(従ってGitHubで静的に管理はしていないフォルダ)がここに来ている。なお、shared/bundleは`capistrano/bundle`が`bundle install --path`で指定するデフォルトのフォルダなんだそうだが、古いバージョンの`capistrano/bundle`ではshared/vendor/bundleにインストールするらしいので要確認。
後半では独自タスクを3つ追加している。
1つ目はdatabase.ymlをアップロードするタスク。デプロイ先にshared/configフォルダを作成した上で、ローカルのconfig/database.ymlをアップロードしている。2つ目は`bundle exec rake db:create`を発動するタスク。Capistranoやcapistrano/railsにはDB作成用のタスクは一切含まれていないので、自力であらかじめ作っておく必要がある。手動で作成したり、Chefなんかで仕込んでおく手もあるのだろうが、ここではCapistranoのタスクとして書いている。必要になるのはもちろん初回1回限りなので、デプロイのルーチンの中には組み込んでいない。
* 参照:[Capistrano3で快適デプロイ生活!! - Less is Best](http://yss44.hatenablog.com/entry/2013/12/01/150215)
3つ目はunicornを再起動するタスク。これはunicorn.capの中で作成した`unicorn:restart`というタスクを呼んでいる。
最後の2行は独自タスクのルーチンへの組み込み。database.ymlのアップロードは真っ先にやらなくてはならないので、`deploy:starting`というデフォルトで言えば最初のタスクのさらに前に組み入れている。一方のunicorn再起動は`deploy:publishing`の後、ほぼすべてのタスクが終わったタイミング。
## unicorn.cap
ほぼほぼ以下エントリーの中身をそのまま使わせてもらいました。
* 参照:[unicorn + rails 用 Capistrano 3 の設定ファイル - Qiita](http://qiita.com/satococoa/items/9b0cc416ffc042680b9b)
異なる箇所は`start_unicorn`の内部処理。元エントリーでは`bundle exec unicorn`を叩いているのだが、自分としては`bundle exec unicorn_rails`を叩く認識だったので書き換えている。ここの書き換えが必要なのかどうかはちょっと自信がない。またコマンドのオプションとして`--path hoge`を指定しているのだが、これはサブディレクトリでRailsアプリを動作させたいため。予定として[http://www.chroju.net/](http://www.chroju.net/)は静的なサイト、www.chroju.net/hogeでアプリごとにフォルダ作って管理としたかったもので。まー、こういう要らんチューニングを最初からやろうとするから迷走するわけなのだが。はじめはマニュアル通りにまず写経すべきだと思います。はい。サブディレクトリ云々の件はまた別途エントリー書きます。
ちなみにパスの指定やら何やらやらないのであれば、[capistrano3-unicorn](https://github.com/tablexi/capistrano3-unicorn)を使うのも手だと思う。
## その他トラブルなど
以上、ここまでの設定にはそれなりに自信がある。とりあえず`bundle exec cap staging deploy`を叩いてエラーが出ないことも確認はした。が、現状アプリは動いてない。。。いや、正確に言うと一度動いたのだが、その後Vagrant落として、セキュリティアップデートのためにiMacも再起動してもう一度やってみたところ、ダメダメになってしまったのだ。何が原因なのやらさっぱりだ。。。トラブルは3つほど遭遇している。
### 1. Gitが通らない
`git ls-remote`で`Permission denid(publickey)`のエラーが出るという事象が発生、その先に進めなくなった。これについてはドンピシャなエントリーを探し当てたので、そのまま解決策を適用したらなんとかなった。なぜこのエラーが起きたのかまではまだ深堀りできてない。
* 参考:[Deploying with Capistrano 3 failing – Permission denied (publickey) | Pete Oliveira](http://peteoliveira.com/deploying-with-capistrano-3-failing-permission-denied-publickey/)
### 2. 404が返される
Nginxは動いている。unicornもプロセスは上がっているのだが、アプリを配置したフォルダを見に行くとThe page you were looking for doesn't exist.というメッセージが返される状態。他の有りもしないフォルダを見に行こうとするとNginxがBad Gatewayを返してくるし、unicorn.stderr.rbにログが残っているのでアクセスはできているようなのだが、なぜ表示に至らないのかわからない。
ちなみにstaging.logにはActionController::RoutingErrorが出ている。???
### 3. Assets周りが不具合起こしている模様
Vagrantを落とす前はアプリ自体つながりはしたのだが、jsとcssが反映されていない状態だった。ソースから探ってjsとcssをブラウザ上で開いてみたのだが、真っ白になっていた。アセットコンパイルのエラーなのかと思い、サーバー上でもコンパイル後のファイルを開いたりしてみたが、こっちは中身がきちんと書かれていた。なんなんだ一体。
以上。だいたい整ったはずなのだが、まだまだ先が長そうでいい加減ゲンナリしている。自分、この手のこと向いてないのかもしれんと思い始めた。。。