自動デプロイ後にレイアウトが崩れる
環境
- AWSの
EC2
でRailsファイルを動かす。 -
nginx
+unicorn
を使用している。 - 手動でデプロイしていたが、
capistrano
を用いて自動でデプロイを試みる。
capコマンドでデプロイ
以下のコマンドをローカルマシンで実行し自動デプロイする。
デプロイは完了するが本番用URLにアクセスするとレイアウトが崩れている。
bundle exec cap production deploy
レイアウトが崩れる原因
config/assets/~
が404
となっているためレイアウトが崩れてしまう。
なぜ404なのか?
以下のconfig/enviroments/production.rb
に書かれている条件式がfalseになっているため。
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
そもそも上記の設定は何か?
静的ファイルを /public ディレクトリから読むかどうか、
これがfalse
になると。ファイルは存在してもpublic
以下からコンパイルされたassetsファイルを読み込んでくれない。ただしWEBサーバー(nginx,apache)はこの設定に関係なくassetsファイルをpublicから読み込める。
unicornがassetsファイルを読み込んでいない
レシーバーである環境変数の値が空のため、presentメソッドの実行結果がfalse
になり、アプリケーションサーバー(ここではunicorn)が上記の設定を処理してくれていない。
つまりこういう事。
config.public_file_server.enabled = false
nginxがassets以下をプロキシしても、unicornの方で処理できていない
手動デプロイ時はassetsがコンパイルされ読み込まれていた
なぜ読み込みが成功していたのか
unicornを起動する際に、環境変数に値を代入していたため。
RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production
なぜCapistrano導入後に読み込みが失敗したのか
capistrano
で自動デプロイを実行する際に変数を設定していないため。
capistranoでunicornをリスタートさせる際は明示的にRAILS_SERVE_STATIC_FILES=1
という設定をしていない。
そのため環境変数に値が入ってなければunicornは読み込み処理をしない。
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
unicornでassetsを処理させるべきか?
そもそもunicornにassetsファイルの読み込み処理をさせるとunicornの負担が増すため宜しくない(らしい)。
なので以下の設定は最初からfalseに設定してしまうと良いらしい。
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
そしてnginxをリバースプロキシにして、静的なコンテンツは直接nginxから取りにいかせる。
テンプレートなど動的な部分はunicornに問い合わせるという流れが良いらしい。
一旦trueにして解決
とは言え今回はちょっとリバースプロキシ的な設定ができているか分からない。
とりあえず以下のようなサイトを参考にして設定ファイルを更新してみたが記述後の検証はまだしていない。
応急処置で対応
config.public_file_server.enabled = true
取り急ぎ非推奨のようだが上記のように値をtrueにして仮解決。
そもそもunicornに処理させるのが間違いなのであれば、
環境変数に値を渡して空かどうか確認して、Trueであれば読み込み...という過程すらも間違いな訳で...。
production.rb
だし他の環境に影響する訳でもなさそうなので一旦ture直書きで。
また続きを書きます。
お世話になったサイト
Rails(Apache+Unicorn)で、public以下のディレクトリの中身が404になる場合の解決策
AWSで、unicorn + nginx + sinatra を動かしてみる
NginxとUnicornの連携設定