前提
詳しい説明は公式ドキュメントを参照するなどして下さい。投げやりですいません……*1。
環境
- Ruby 2.5.3
- Rails 5.2.1
- Capistrano Version: 3.11.0 (Rake Version: 12.3.1)
3つの設定ファイル
Capfile
と config/deploy.rb
と config/deploy/production.rb
の内容を書きます。config/deploy/production.rb
については他の環境へのデプロイの場合は適宜編集をすればよいです。
なお、Pumaに関係ないところは極力省きます。
1. Capfile
(省略) require 'capistrano/puma' install_plugin Capistrano::Puma (省略)
2. config/deploy.rb
ここキモです。
(省略) namespace :deploy do task :restart_puma do invoke 'puma:stop' invoke! 'puma:start' end end after 'deploy:finishing', 'deploy:restart_puma' (省略)
3. config/deploy/production.rb
Puma
は、ポート番号を指定して起動するものとします。
(省略) set :puma_init_active_record, true (省略)
上記だけ書いて、他の set
は要らないのかと思うでしょうが、デフォルト設定で行く場合は実はこれで大丈夫です。ただ、いろいろ書き加えたほうがいいのでそれは後述します。
詳細
3つのファイルそれぞれの内容の詳細を書きます。
1. Capfile
の詳細
Capistrano::Puma
を使うために require 'capistrano/puma'
と require
しています*2。install_plugin
を書くところがキモです。
2. config/deploy.rb
の詳細
実はここの deploy タスクの部分に追加をしなくても、ログを見ると puma:restart
してくれるように見えます。
が、私の環境では実際には restart されていなかったため、このような記述をしています。
この記述にはポイントがいくつかあります。
(a) invoke ではなく invoke! でなければいけない
まず、invoke
ではなく invoke!
である必要があります。これは、タスク実行時の警告メッセージにて注意されます。
Skipping task `puma:start'. Capistrano tasks may only be invoked once. Since task `puma:start' was previously invoked, invoke("puma:start") at /Users/FOOBAR/PATH/TO/vendor/bundle/ruby/2.5.0/bundler/gems/capistrano-puma-09b11cafb2cf/lib/capistrano/tasks/puma.rake:71 will be skipped. If you really meant to run this task again, use invoke!("puma:start") THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF CAPISTRANO. Please join the conversation here if this affects you. https://github.com/capistrano/capistrano/issues/1686
上記に挙げられている Issue
はこれですね。
(b) invoke! 'puma:restart' ではだめ
invoke! 'puma:restart'
ではなく、invoke 'puma:stop'
してから invoke! 'puma:start'
する必要があります。これは Stack Overflow で知りました*3。
なお、invoke! 'puma:restart'
でダメな理由は Rake::Task['puma:restart'].reenable
を書いていないからではないか、と思いましたが、書いてもダメでした。
3. config/deploy/production.rb
の詳細
本当に最小限の動作ならば set :puma_init_active_record, true
だけでいい*4のですが、現実的には以下の内容も設定しておいたほうがいいでしょう。
各種のパスは好きなように設定してよいです。ただ、#{shared_path}
の場合は予めデプロイ先にディレクトリが存在していなければいけません。
set :puma_conf, "#{shared_path}/config/puma.production.rb" set :puma_state, "#{shared_path}/tmp/pids/puma.state" set :puma_pid, "#{shared_path}/tmp/pids/puma.pid" set :puma_conf, "#{shared_path}/config/puma.production.rb" set :puma_access_log, "#{release_path}/log/puma.access.log" set :puma_error_log, "#{release_path}/log/puma.error.log" set :puma_preload_app, true set :puma_worker_timeout, nil set :puma_init_active_record, true
上記の設定をすることで、次の「極めて重要なこと」につなげられます。
極めて重要なこと(ここが一番大事かも)
上記の3つのファイルの設定が終わりました。ここで以下のコマンドを入力して Puma の設定ファイルのひな型を作ります。
$ cap production puma:config
上記のコマンドにより、config/deploy/production.rb
内の set :puma_conf
で設定した場所に Puma の設定ファイルのひな型が作成されます*5。
config/deploy/production.rb
の内容が反映された設定ファイルが作られていますので、基本的にはなにもいじくらないで大丈夫です。置き場所も変える必要はありません*6。
ただ一点、ポート指定で Puma を起動したい場合には以下の一行を追加する必要があります。これで 12345
ポートで待ち受けます。
ポート指定した場合は bind
は以下のようにコメントアウトして良いでしょう。
port ENV.fetch('PORT') { 12345 } # bind 'unix:///PATH/TO/shared/tmp/sockets/puma.sock'
なお、Puma の設定は上記ファイルを見ますので、config/puma.rb
の内容は無視されます。ただ、ファイルそのものを削除すると警告が出てしまうので、本文を全てコメントアウトするか本文は全て削除してファイルだけ残す、という感じでよいのではないでしょうか*7。
補足: restart がダメな場合にどういう現象が起きるか
restart に失敗する場合は既存の .pid
ファイルが消えます。.pid
ファイルが消えた状態ですと起動に成功します。起動に成功して .pid
が作られた状態で restart に失敗すると .pid
ファイルが消えます。
この繰り返しになりました。
補足: これでいいとは思えませんが……
このやり方や結果が正しいとはどう考えても思えませんが、ハマりすぎて泣きそうなのでいったんここまでとしました。
デプロイのたびに下記のようなメッセージが出て心臓に悪いです。
Skipping task 'puma:start'. Capistrano tasks may only be invoked once.
という警告メッセージが出ることから、gem を用いれば Capistrano は標準で(何もしなくても) puma:restart
してくれます。しかしその restart がうまくいかないため、無理やり再度 invoke!
をしているという流れです。
各命令などの詳細は公式ドキュメントを参照するとよいと思います*8。
補足: set :puma_hogehoge
の記述を config/deploy.rb
に書いても反映されない
set :puma_hogehoge
の記述は面倒でも各デプロイ環境の設定ファイルに書かないといけないようです*9。そのため DRY ではなくなりますが、しょうがないようです。
補足: 参考にしようとした記事
ちょっと古いだけでバージョン違いでうまく適用できないですね……。