Capistrano3におけるRailsのデプロイタスクの内部実装


CapistranoはRailsアプリケーション専用のデプロイツールとして生まれたという歴史的な背景から、今までRails用の機能がCoreモジュールに組み込まれていましたが、昨年リリースされたCapistrano3からはそういった特定のドメインに特化した機能がCoreから排除されて別のRubygemsとして提供されるようになりました。

本稿では、それらRailsデプロイまわりの機能について見ていきたいと思います。

参考

Capistrano3のデプロイフレームワークについては下記の記事を参照してください。

capistrano/railsとcapistrano/bundler

具体的にはRailsまわりの機能はcapistrano-railscapistrano-bundlerというRubygemsに分割されています。

とりあえずGemfileに入れときましょう。

Gemfile
group :development do
  gem 'capistrano', '~> 3.0'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
end

そしてCapfileで require します。

Capfile
require 'capistrano/setup'   # おまじない
require 'capistrano/deploy'

require 'capistrano/rails'  # 内部でcapistrano/bundlerをrequireしてる

# 個別に書く場合
require 'capistrano/bundler'  # rails使う場合はbundlerは必須、、ですよね?
require 'capistrano/rails/assets'  # asset:precompileとかが定義されてる
require 'capistrano/rails/migrations'  # db:migrateとかが定義されてる

capistrano/railsによってdeploy:compile_assetsとdeploy:migrateが、capistrano/bundlerによってbundler:installがそれぞれ追加されます。

タスク 内容 タイミング
deploy:compile_assets Assetsを1つのファイルにまとめて圧縮する deploy:updatedの後
deploy:normalize_assets Assetsのタイムスタンプを更新する deploy:compile_assetsの直後
deploy:migrate DBのmigrationを実行する deploy:updatedの後
bundler:install Bundlerを実行する deploy:updatedの後

と、こんな感じでcapistrano/railsやcapistrano/bundlerを require すると自動的にcapistrano/frameworkのフックに必要なタスクがぶら下がって、デプロイプロセスが動くようになっています。

Unicornをリロードする

後はこうしてサーバ上に展開された新しいアプリケーションが動作するようにUnicornをリロードするだけです。Unicornのタスクを記述する際は @satococoa さんの投稿が参考になります。

仮にこちらの記事のようにunicorn:restartタスクを作ったのなら、あとはこれをdeployタスクの中で実行するだけです。v3.0まではdeployタスクを実行後に自動的にdeploy:restartというタスクが実行されるので、そこの中でinvokeします。v3.1移行は実行されないので、publishingタスクの後で実行されるように設定します。

config/deploy.rb
namespace :deploy do
  after :publishing, :restart

  desc 'Restart application'
  task :restart do
    invoke 'unicorn:restart'
  end
end

これで cap staging deploy を実行すればデプロイ完了後にUnicornが自動的に再起動されるようになります。