ECSでRailsのassetsを配信する方法

これまでのまとめ

今までGitHub Actionsを用いてECSデプロイする方法を調査してきました。そして、なんとかECSにデプロイできるところまできました。

今回は、デプロイできるようになったものの、アセットが表示されなかったときの対応方法をまとめたいと思います。

状況の確認

ECSは起動タイプにFargateを選択していました。ですのでコンテナの状況はCloudWatchに流れてくるログからのみ知ることができました。

ログにはアセットが見つからないと言う情報だけしかありませんでした。最初はアセットのプリコンパイルが失敗しているのかと思い、コンテナ作成時にプリコンパイルしたり、ECSで起動時にプリコンパイルしたりしましたが状況は変わらずでした。

起動タイプEC2で試す

やはりこういうときはコンテナにアクセスできた方がデバッグが早いです。面倒でしたが起動タイプEC2で起動し、コンテナにアクセスしました。

アセット類はRailsコンテナ内に存在していました。

原因の調査

この時点ではまだ良くわからなかったので、アプリケーションのURLではなく、アセット単体のURLにアクセスしてみました。

するとnginxが404を返してきます。nginxが404を返してくる、そもそもupstreamのRailsにリクエストをフォワードしていないのでは?と思ってnginxの設定を調べてみると、nginxの設定はnginxとRailsが一つのサーバで動作していた時のままでした。

  • nginxのDocumentRootはRAILS_ROOT/public
  • locationの設定もそのまま
  • アセットはnginxが処理し、それ以外はupstreamのRailsにフォワード

これではアセットが表示されないのも当然です。nginxとRailsを別コンテナで動かすという単一責務の法則に従ったことで、以前の設定が使えなくなっていました。

対応

まず、全てのアクセスをupstreamにフォワードするようnginxの設定を変更します。locationの優先順位がちゃんと理解できていなかったことを思い知らされました。nginxについて再度学びたいと思います(後日記載します)。

nginxの設定を変更すると、エラー表示がnginxからRailsに変わりました。これでリクエストがRailsにフォワードされていることがわかります。

Railsのエラーメッセージを確認すると、ActionController::RoutingErrorとなっていて、アセットファイルへのrouteがないと言っています。

原因を確認すると、静的ファイルの配信設定ができていないようでした

1
2
3
# 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?

config/environments/下のファイルに上記のように記載されていたので、タスク定義ファイルに

1
2
3
"environment": [
{ "name": "RAILS_SERVE_STATIC_FILES", "value": "true" }
],

と設定することで、静的ファイルの配信ができるようになりました。

まとめ

nginxとRailsが同じサーバで動作することに慣れてしまっていたので、原因がわかるまで時間がかかってしまいました。わかってしまえばそんなに大したことではないのですが、わかるまでが大変ですね…

今回のことでRailsやnginxの設定がわかっていないことがよくわかりました。nginxの設定、とくにlocationの設定はちゃんと理解しておくべきだと思うので、これから重点的に学びたいと思います。