capistrano 3.xでrails appをdeployするときにハマったこと

railsアプリをデプロイするときに最近流行のCIってやつに乗ってみるかと思って、普段なら手動デプロイしていたところを自動デプロイすることにした。
調べてみたらどうやらcapistranoという、ほぼデファクトスタンダードになっているgemがあるとのことだったので、使うことにした。
ところがこのcapistrano、2013年8月頃に3.xにメジャーアップデートしたらしい。
しかも、このアップデートで2.x系との互換性を捨ててしまったらしく、3.x向けの情報がやたらと少ない。
ここでおとなしく2.xを使えばよかったものの、新物に目がない僕は3.xを使うという愚行を下してしまったのだった…

というわけで、1日半くらいはハマりました。
この記事で少しでも多くの人がcapistranoを上手く使いこなし、自動デプロイの恩恵に与れることを期待しています。

capistranoの基本的な使い方

僕はこの記事を参考にしました。
Capistrano 3系でRails4.1のデプロイ[rbenv][rvm][ruby2.1] - 酒と泪とRubyとRailsと
ひとまずは、この通りにやってみます。

config/deploy.rb、config/deploy/production.rbあたりを書いて、

bundle exec cap production deploy:check
bundle exec cap production deploy

を実行します。
僕の場合は、最後のコマンドを実行するところで大量のエラーが発生しました。

SSHが通らない

SSHKit::Runner::ExecuteError: Exception while executing on host example.com: Authentication failed for user user@example.com

こんなエラーが出ました。これは、SSHの設定が間違っている可能性が高いです。
僕の場合は、config/deploy/production.rbに設定しているssh_options[:key]が間違っていました。
ここに設定するのは、自分のローカルマシンのSSH公開鍵です。
僕は間違えてサーバの公開鍵のパスを指定していました。

サーバ上でリポジトリをcloneできない

executing locally: "git ls-remote git@github.com:myuser/myrepo.git HEAD"
Permission denied (publickey).
fatal: Could not read from remote repository.

こんな感じのエラーです。permission deniedということは、これもSSHの認証周りか?と思いまずはサーバ上で

git ls-remote git@github.com:myuser/myrepo.git HEAD

できるか試してみました。すると、秘密鍵パスフレーズを要求されました。
パスフレーズを正しく入れると、きちんとエラーなく実行できました。
つまり、capistranoパスフレーズの入力でこけていたみたいです。
本当はcapistranoがユーザにパスフレーズの入力を促すべきなのでしょうが、現在パスフレーズの入力コンソール周りにバグがあるらしく、エンターを押しても入力が終了しません。
(デフォルトではパスフレーズを聞いてきませんが、config/deploy.rbでset :pty, trueとすると聞いてきます)
仕方ないので、とりあえずパスフレーズ無しの秘密鍵を生成してgithub等に登録します。

rbenv: bundle: command not found

このエラーが出たときは、まずは最初の参考記事の通り、rbenvの設定に問題がないか見てみてください。

set :rbenv_type, :user
set :rbenv_ruby, '2.0.0-p451'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
set :rbenv_roles, :all

(参考記事とrubyのバージョンが違います)
その後、サーバ側のrbenvに対応するバージョンのrubyがrbenvでインストールされているか確認してください。

mysql.h missingでmysql2がインストールできない

これは、サーバにmysql-develをインストールすることで解決できます。
ところが、僕の場合は

sudo yum -y install mysql-devel

だけではエラーが出てインストールできませんでした。

sudo yum -y install mysql-devel.x86_64 --enablerepo=remi

でインストールできました。

【参考】mysql2 - sudo yum install mysql-devel でインストール出来ない - Qiita

Could not locate Gemfile

capistranoがGemfileを見つけられないエラーです。
僕の場合はrailsのアプリがgitリポジトリのサブディレクトリに含まれていました。
一応capistrano側でサブディレクトリを指定する方法もあるみたいですが、僕が見つけられたのは2.xで通用する方法ばかりで、3.xで試してもどうもうまくいきませんでした。
gitリポジトリのサブディレクトリを切り出して新しいリポジトリにする方法が紹介されていたので、試してみるといいでしょう。
ちなみに僕の場合は、諸事情があって他の人の未stage済の変更があってgit filter-branchできなかったので、諦めてrailsアプリを丸ごとcpして切り出しました。
なんか上手い方法はないものだろうか…

【参考】capistrano で サブディレクトリ 内の 特定アプリ をデプロイする - てしりこじり
【参考】Gitリポジトリ中のサブディレクトリを別のリポジトリにする - 北海道苫小牧市出身のPGが書くブログ

終わりに

僕がcapistrano側でハマったのはだいたいこれくらいでした。
実は、railsアプリをdeployするのは初めてだったので、capistranoでうまくdeployした後にApache+Passenger+Railsを連携させるところでも少しハマりました。
その部分についてはcapistranoよりは情報が多いと思うので、ここでは割愛させていただきます。