5分でRailsアプリをデプロイ。
5分でRailsアプリを本番環境へデプロイします。
ソフトウェアプログラミングを覚えたと思ったらサーバにアプリ置けないのって辛いですよね。
環境
nginx/1.12.0
centos6
Rails4.2.5
Capistranoインストール
デプロイを自動化できるプラグインです。
/Gemfile
group :development do gem 'web-console', '~> 2.0' gem 'spring' gem 'capistrano' #追加 gem 'capistrano-bundler' #追加 gem 'capistrano-rbenv' #追加 gem 'capistrano-rails' #追加 end
使用するGemはこれで十分です。
bundle
Capistranoの設定
bundle exec cap install
rootディレクトリにCapfileが作成されますので編集します。
/Capfile
require "capistrano/scm/git" require 'capistrano/setup' require 'capistrano/deploy' require 'capistrano/rails' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/rbenv' require 'capistrano/bundler' Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } install_plugin Capistrano::SCM::Git
とりあえず、これを書いて置けば通ります。
あと、2つファイルを修正します。
/config/deploy.rb
lock "3.8.1" set :application, "アプリ名(なんでもよろし)" set :repo_url, "GitHubのrepository名" set :deploy_to, '/home/ユーザー名/アプリ名/' set :keep_releases, 5 #気にしない set :ssh_options, :port => "ポート番号" #SSH接続に使うポート名 set :rbenv_type, :system # :system or :user set :rbenv_ruby, '2.3.1'#rubyのバージョン #気にしない↓↓↓ 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 # default value set :linked_dirs, %w{bin log tmp/backup tmp/pids tmp/cache tmp/sockets vendor/bundle} set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid" set :bundle_jobs, 4 after 'deploy:publishing', 'deploy:restart' namespace :deploy do task :restart do invoke 'unicorn:restart' end end # Default
上記で大事なことは上半分です。
細かいことはデプロイに慣れてから徐々にカスタマイズしてください。
set :application, "アプリ名(なんでもよろし)"
制作したアプリの名前を書けばいいと思います。
set :repo_url, "GitHubのrepository名"
これは大事です。
デプロイしたいアプリを収めてるリポジトリのURLを入力します。
ダウンロードやクローンの為に用意されてます。
set :deploy_to, '/home/ユーザー名/アプリ名/'
CentOS内で入った時に、lsコマンドを打つと現れると思います。
デフォルトではないかもしれないのでなければmkdirで作ってください。
Home下の階層にユーザー名の階層も作っておきましょう。
それからデプロイするアプリをどこに置くかを指定できるのが上記の処理です。
「アプリ名」の部分にアプリがデプロイされます。
set :ssh_options, :port => "ポート番号" #SSH接続に使うポート名
おそらく、SSHは済んでいると思うので、
その接続に使うポート番号を書いてくださいね。
今回の私の設定は以下です。
set :application, "deploy" set :repo_url, "https://github.com/sagaekeiga/deploy.git" set :deploy_to, '/home/anime/deploy_sample/' set :keep_releases, 5 set :ssh_options, :port => "内緒"
最後にdeploy/production.rbを編集して終わりです。
ローカルにありますよ。
deploy/production.rb
set :branch, 'master' role :app, %w{ユーザー名@IPアドレス} role :web, %w{ユーザー名@IPアドレス} role :db, %w{ユーザー名@IPアドレス} server 'IPアドレス', user: 'ユーザー名', roles: %w{web app db} set :ssh_options, { forward_agent: true, auth_methods: %w(publickey), port: ポート番号 }
こちらはユーザー名・IPアドレス・ポート番号を設定するだけです。
それ以外はまたカスタマイズしてください。
デプロイ
ここは一応確認ですが、
ローカルのアプリ内に潜んでいるCapistranoがGitにあるファイルをサーバーへ送ってくれます。
ですので、最新のアプリを更新(プッシュ)します。
デプロイ時はデータの作成(migrate)などCapistranoが一通り行ってくれます。
$ git add . $ git commit -m デプロイ $ git push
最後にデプロイ!!
$ cap production deploy
確認しましょう。
サーバーの中はこのようになりました。
$ pwd /home/anime/deploy_sample/current/app
次はWebサーバー(nginx)の設定をします。
5分でActionCableの実装する!
ActionCableを実装します。
機能に関する詳細はこちらです。
RoRでリアルタイム通信を実現することができます。
ACは、Rails5以降の機能ですので、5未満の方はアップデートをしてからこの記事を読み進めてくださいね。
Git
こちらは会員登録が必要になりますので無理なさらず。
私が個人で作ったアプリです。
コントローラーの作成
$ rails g controller chat show
モデルの作成
$ rails g model message body:text
チャット用チャンネルを作成
$ rails g channel chat speak
$ rails db:migrate
チャット用チャンネルを作成
$ rails g channel chat speak
これまで作成したものを確認しましょう。
$ rails server
/chat/showで画面が表示されます。
ソースコードの確認
ブラウザでページソースを表示してみましょう。<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Faction_cable.self-17ebe4af84895fa064a951f57476799066237d7bb5dc4dc351a8b01cca19cce9.js%3Fbody%3D1%22%20data-turbolinks-track%3D%22reload%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" /> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fcable.self-6e0514260c1aa76eaf252412ce74e63f68819fd19bf740595f592c5ba4c36537.js%3Fbody%3D1%22%20data-turbolinks-track%3D%22reload%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" /> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fchannels%2Fchat.self-660d1dfffd7c22551eb29709ea5f789dbd62d8a2e602aa8e9126bd90ab1de200.js%3Fbody%3D1%22%20data-turbolinks-track%3D%22reload%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" /> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fchat.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js%3Fbody%3D1%22%20data-turbolinks-track%3D%22reload%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" /> <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fapplication.self-b89234cf2659d7fedea75bca0b8d231ad7dfc2f3f57fcbaf5f44ed9dc384137b.js%3Fbody%3D1%22%20data-turbolinks-track%3D%22reload%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
ACが読み込まれていることがわかりますね。
接続エラーの解決
ここでデベロッパーコンソールを開くとエラーが出ていることがわかります。WebSocket connection to '~~/cable' failed: WebSocket is closed before the connection is established.
ソケットが閉じているので接続できません〜
という意味ですので、きちんと開いてあげましょう。
3つのポイントがあります。
①Pumaのインストール
ActionCableのようにリアルタイム通信を実現する為に特殊なソケットを利用する場合はWebサーバを対応しているPumaにする必要があります。
/Gemfile
gem 'puma' bundle
サーバを再起動してみてください。
するとログが以下のように変化します。
=> Booting Puma => Rails 5.0.0 application starting in development on http://0.0.0.0:8080 => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.8.2 (ruby 2.3.0-p0), codename: Sassy Salamander * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://0.0.0.0:8080 Use Ctrl-C to stop
① development.rbの編集
ActionCableにどのドメインを使用し、また動いていいよと命令を出してあげます。
以下を加えてください。
場所は問いません。
config/environments/development.rb
config.action_cable.allowed_request_origins = [ 'あなたのドメイン' ] ActionCable.server.config.disable_request_forgery_protection = true
ドメイン例(clou9を使用)
config.action_cable.allowed_request_origins = [ 'action-cable-sagae.c9users.io' ]
③ Redisを起動
Rails5にはredisサーバーが用意されてます。
このサーバーを動かすことでACを使うことができるようになります。
ターミナル
$ redis-server
それでは、コンソールをみてください。
どうでしょうか?
先ほどの接続エラーは出なくなると思います。
メッセージのブロードキャスト
クライアント側にメッセージを要求します。
ブラウザで入力した値を取得する処理になります。
app/assets/javascripts/channels/chat.coffee
App.room = App.cable.subscriptions.create "ChatChannel", connected: -> disconnected: -> received: (data) -> $('#messages').append data['message'] speak: (message) -> @perform 'speak', message: message
次に受け取ったデータをクライアントに返します。
入力された値をブラウザに表示します。
app/channels/chat_channel.rb
# chatチャンネル接続時にコールされる def subscribed stream_from "chat_channel" ActionCable.server.broadcast 'chat_channel', message: 'connected.' end # chatチャンネルのspeakメソッドは、受け取ったメッセージを全クライアントにブロードキャストする def speak(data) ActionCable.server.broadcast 'chat_channel', message: data['message'] end
これでデータの受け渡しができるようになりました。
ここで、一度サーバを再起動しましょう。
Pumaとredisどちらもです。
control+cで停止、起動は先ほどのコマンドを使ってください。
フォームの作成
以下のコードでユーザーの入力値を取得できます。app/views/chat/show.html.erb
<ul id="messages"> </ul> <form> <label>say something: <input type="text" data-behavior="chat_input"></label> </form>
app/assets/javascripts/channels/chat.coffee
↑先ほど書いたコードの下に書いてください。 $(document).on 'keypress', '[data-behavior~=chat_input]', (event) -> if event.keyCode is 13 # return = send App.room.speak event.target.value event.target.value = '' event.preventDefault()
入力値の表示
こちらは普通のJsの処理ですね。app/assets/javascripts/channels/chat.coffee
App.chat = App.cable.subscriptions.create "ChatChannel", received: (data) -> $('#messages').append ' <li>' + data['message'] + '</li>' ↓先ほど書いたコードの上に書いてください。