capistrano3を使用してEC2でのデプロイでエラー


具体的な状況

capistrano3を使用してRails5のアプリケーションをデプロイしよう(on AWSのEC2)としていました。
以下のようなファイル構成で$ bundle exec cap production deployを叩きました。

capfile
require "capistrano/setup"
require "capistrano/deploy"

require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano3/unicorn'

require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

config/deploy.rb
# config valid only for current version of Capistrano
lock "3.8.0"

set :application, "chat-space"
set :repo_url, "[email protected]:MY_NAME/APPLICATION_NAME.git"

set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')

set :rbenv_type, :user
set :rbenv_ruby, '2.3.1'

set :ssh_options, auth_methods: ['publickey'],
                  keys: ['~/.ssh/KEY_NAME.pem']

set :unicorn_rack_env, 'production'
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
set :unicorn_config_path, -> { "#{current_path}/config/unicorn.rb" }

set :keep_releases, 5

after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
  task :restart do
    invoke 'unicorn:restart'
  end


end

config/unicorn.rb
app_path = File.expand_path('../../../', __FILE__)

worker_processes 1

working_directory app_path
pid "#{app/path}/tmp/pids/unicorn.pid"
stderr_path "#{app_path}/log/unicorn.stderr.log"
stdout_path "#{app_path}/log/unicorn.stdout.log"

listen 3000
timeout 60

preload_app true
GC.respond_to?(:copy_on_write_friendly=) && GC.copy_on_write_friendly = true

check_client_connection false

run_once = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) &&
    ActiveRecord::Base.connection.disconnect!

  if run_once
    run_once = false # prevent from firing again
  end

  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exist?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH => e
      logger.error e
    end
  end
end

after_fork do |_server, _worker|
  defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection
end


以下のようなエラーメッセージが出現しました。(もっと長いのですが、エラーの肝的な部分をのみを掲載してます、以下のエラーメッセージについても同じです)

The deploy has failed with an error: Exception while executing as ec2-user@~IP~: kill exit status: 1
kill stdout: Nothing written
kill stderr: cat: /var/www/APPLICATION_NAME/shared/tmp/pids/unicorn.pid: そのようなファイルやディレクトリはありません

もう一回、諦めずに叩いてみると、

 DEBUG [cb974f74] Finished in 0.068 seconds with exit status 1 (failed).

  INFO [8921b47f] Running $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/chat-space/current/config/unicorn.rb -E production -D  as [email protected]

 DEBUG [8921b47f] Command: cd /var/www/APPLICATION_NAME/current && ( export RBENV_ROOT="$HOME/.rbenv" RBENV_VERSION="2.3.1" RAILS_ENV="production" ; $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/chat-space/current/config/unicorn.rb -E production -D  )

 DEBUG [8921b47f]   master failed to start, check stderr log for details

以下、何回叩いてみても同じエラーメッセージが出ます。

対策

unicorn関連のエラーというのは、エラーメッセージから理解できます。
なので、エラーログを見てみます。config/unicorn.rbでエラーログはAPPLICATION_NAME/log/unicorn.stderr.logに吐くようになっていますので、
ec2インスタンス上で確認しますとAlready running on PIDというメッセージを見つけました。
どうやらunicornのpidがうまく機能していなかったようです。

いろいろ調べてみましたが、僕が救われたのは以下のポストです。

capistranoでunicornのoldプロセスが殺せない
http://h3poteto.hatenablog.com/entry/2015/05/10/192100

このポストの要諦は、unicornとcapistranoのpidの設定が噛み合ってないとpidでトラブルを起こすからそれをなんとかしましょうというものです。

自分のファイルのpid設定を見直してみると

config/deploy.rb
#関係部分のみ抜粋
set :unicorn_pid, -> { "#{shared_path}/tmp/pids/unicorn.pid" }
config/unicorn.rb
#関係部分のみ抜粋
app_path = File.expand_path('../../../', __FILE__)
pid "#{app_path}/tmp/pids/unicorn.pid"

ん???
pidファイルの指定の仕方が違うぞ!と気づきました。
shared_pathから始まるのか、app_pathから始まるのかが違っていました。

↑のポストではsharedに合わせたとなっておりましたので、それに倣い、unicorn.rbにshared_pathという変数も定義しました。

unicorn.rb
app_path = File.expand_path('../../../', __FILE__)
shared_path = File.expand_path('../../../shared/', __FILE__)

pid "#{shared_path}/tmp/pids/unicorn.pid"

一回これで$ bundle exec cap production deployを叩いてみると、まだAlready running on PIDが出たので、ec2上から手動でunicornのプロセスをkillしました。
そしてもう一度$ bundle exec cap production deployを叩くと、capistranoの自動デプロイ機能がうまく機能してくれました。

その後

自動デプロイはうまくいってくれるようになりましたが、更新した瞬間、レイアウトが崩れました。
cssやjsを取り込むためのassets関連がまだまだうまく機能していないようです。
また解決したら報告します。
初めてのデプロイ本当にしんどい!!!!!!!!!!!!!

170513追記

いろいろやりたくて手動でunicornのプロセスをkillして、自動デプロイしたらまたエラーを履くようになってしまった。。。
bash: 0 行: kill: (5147) - そのようなプロセスはありません
だそうで、、、

なんとなく、ポートを3000に指定してアクセスするとcssもjsも効いてるページにたどり着いたんですが、原因がよくわかりません。
ここら辺の勉強が足りないですね…!

170516追記

以下の記事にあるコマンドで解決しました。
素晴らしい記事をありがとうございました。

$ RAILS_ENV=production bundle exec rake assets:precompile assets:clean