Rails5のActionCableをCapistrano経由でデプロイ

  • 40
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Rails 5の目玉機能の一つに、WebSocketsを容易に利用できるActionCableがあります。Rails 4でもgemで提供されてましたが、Rails 5で本体にマージされました。しかし本番環境の情報が少なかったので、記事にまとめました。ActionCableを使ったRails 5アプリは、以下の記事がわかりやすいです。

この例ではdevelopment環境およびHerokuでは動作しますが、この記事は本番環境のnginxを自前で設定してゆきます。

動作環境と構成

フロントのWebサーバにはnginxを、RackサーバにはPumaを使い、Capistrano3でデプロイします。UnicornをRackサーバに使うと、WebSocketsサーバも別に作成する必要があるので、今回はPumaを使います。Pumaとnginxの処理は puma.sock 経由で行います。デプロイおよびPumaの制御にはCapistranoを使います。サービスとして起動するには、jungleまたはsystemdの設定を自前で用意すれば良さそうですが、ここでは触れません。

ActionCableのデフォルトに従い/cableをWebSocketsのパスに、つまりws://your-domain.example.com/cable(またはwss://your-domain.example.com/cable)からWebSocketsに接続します。

Railsアプリの設定

まずRailsアプリ側で、ActionCableが許可するホストを設定します。nginxとRailsアプリが同サーバ上でも、サーバのホストを許可する必要があります(Allowed Request Origins)。

config/environments/production.rb
config.action_cable.allowed_request_origins = [ 'https://your-domain.example.com' ]

Capistranoの設定とデプロイ

capistrano-pumaというgemを使うと、サーバ側のpumaを手元から制御できます。Gemfilecapistrano3-pumacapistrano-puma は別のgemないので注意!)を追加して、Capfile に設定します。

Gemfile
gem 'capistrano3-puma' , group: :development
Capfile
require 'capistrano/puma'

以上でCapistrano経由で本番環境のpumaを制御できます。

(bundle exec) cap production puma:start

この時 puma:config タスクが走り、pumaの設定ファイルがデプロイ先の "#{shared_path}/puma.rb" に作成されます。pumaの設定ファイルは config/deploy.rb を元に生成されます。設定項目はcapistrano-pumaのREADMEにあります。デフォルトでは、pumaのsockファイルが "#{shared_path}/tmp/sockets/puma.sock" に配置されます。つまり puma:start を走らせると"#{shared_path}/tmp/sockets/puma.sock" 越しにRailsアプリにアクセスできるので、nginxはこのファイルを見に行くよう設定します。

nginxの設定

通常のHTTPリクエストは、Unicorn同様upstreamにソケットを指定します。WebSocketsに対するリクエスト(/cable)はHTTPバージョンとヘッダを書き換えて同じソケットに渡します。

nginx.conf
http {
  upstream puma {
    server unix:/path-to-your-project/tmp/sockets/puma.sock;
  }

  server {
    # General web access
    try_files $uri $uri/index.html $uri.html @webapp;
    location @webapp {
      root /path-to-your-project/public/;
      proxy_pass http://puma;
    }

    # WebSocket configure
    location /cable {
      proxy_pass http://puma;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
  }
}

繋がらないときは

検証用にcURLでWebSockets通信もできますが、wscatが便利です。

wscat -c ws://your-domain.example.com/cable    # or wss://... in SSL version

設定ができてなければエラーが帰ってきて、反応が無いときは正常に通信できてる場合が多いです。正しく通信できないときはログとにらめっこしましょう。

参考