概要
先日、「AWS - Capistranoを使ってデプロイした際のエラー奮闘記」を書きました。
今回は、そのデプロイ後に起きた「502」エラーの対処法を述べていきます。
デプロイには成功したのに、アプリが表示されない、といった方の参考になれば幸いです。
前提として、デプロイにはCapistranoを利用しています。
構成は以下の通りです。
- macOS Monterey 12.3.1 (M1)
- Ruby 3.1.1
- Rails 6.1.5
- nginx
- puma
- MariaDB 10.6.7
- EC2(Amazon Linux 2 AMI / t2.micro)
- RDS
こんな感じです。
「502」エラーとは
そもそも「502」エラーとは何なのでしょうか。
502エラーとは、Webサーバで起きるエラーの種類の一つで、目的地のWebサーバが機能していないことを、経路途上にある中継サーバ(プロキシなど)が報告するもの。
引用先:IT用語辞典 e-Words
ステータスコード500番台はサーバ側の問題であり、502は"Bad Gateway"というエラーメッセージを吐き出します。目的のサーバがレスポンスを正常に返してくれないよ、というサインです。
実際に、私がアプリケーションにアクセスした際の画面が以下です。
これだけだと内部がどうなっているかわからないので、エラーログを実際に見ていきます。
エラーログを見る
以降では2つのターミナルが登場してきます。
*ローカルのターミナル => 通常のターミナル
*サーバのターミナル => EC2にログインしている状態のターミナル
以下をローカルのターミナルで実行してみてください。
$ curl -I <Elastic IP>
HTTP/1.1 502 Bad Gateway
:
こうですね。「502」エラーが表示されています。
では、次にサーバ側のエラーログを見て具体的にどうなっているか確認をします。
ログまでのパスは構成によって異なりますので、ご自身でご確認ください。
筆者の場合、以下の通りです。
$ cd /var/www/$APP_NAME/shared/log
# 移動ができたらディレクトリ内を確認
$ ls
=> nginx.access.log nginx.error.log production.log
# catコマンドでファイルの中身を確認
$ cat nginx.error.log
=> 2022/**/** **:**:** [crit] : *6 connect() to unix:/var/www/$APP_NAME/shared/tmp/sockets/puma.sock failed (2: No such file or directory) while connecting to upstream, client: ****, server: localhost, request: "HEAD / HTTP/1.1", upstream: "http://unix:/var/www/$APP_NAME/shared/tmp/sockets/puma.sock:/", host: "****"
すると、どうやら2: No such file or directory
(ファイルもしくはディレクトリがないよ)と言ってますね。(*「$APP_NAME」は事前にアプリ名を変数に格納しているのでアプリ名と思ってください)
では、実際にこのファイルもしくはディレクトリがないか確認をします。
以下のコマンドを実行します。
# ルートディレクトリから
$ cd /var/www/$APP_NAME/shared/tmp/sockets
$ ls
>
特に何も表示されていないということはpuma.sock
ファイルが作成されていないということになります。
puma.sock
とは
puma.sock
とは、ソケット通信を行なってWebサーバと連携をするために必要なソケットです。
つまり、pumaを起動するのに必要なファイルということです。
そのため、Pumaの設定を編集する必要があります。
# 以下の部分をコメントアウト
# port ENV.fetch("PORT", 3000)
# socketの設定
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"
port ENV.fetch("PORT", 3000)
をコメントアウトせずデプロイを行うと、こちらを認識してしまい、うまく動作しないことがあるそうなので、コメントアウトをしておきましょう。
で、す、が
筆者の場合、これを修正してコミット、プッシュ、デプロイ後
確認をするも改善はしませんでした。
#{Rails.root}
の中身を確認しよう
そもそも#{Rails.root}
の中身はどういったものなのでしょうか。
この確認を怠ると余計に時間を取られます。
筆者の場合、以下の通りでした。
*筆者の場合、current
配下にapp
ディレクトリなどが格納されています。ここは環境によって異なるのでご自身で確認してください。
# サーバのルートディレクトリで実行
$ cd /var/www/$APP_NAME/current
$ yarn install --check-files
yarn install v1.22.18
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 8.01s.
# サーバ側で'rails c'を使用するためには以下のコマンド
$ bin/rails c -e production
Loading production environment (Rails 6.1.5)
irb(main):001:0> Rails.root
=> #<Pathname:/var/www/$APP_NAME/releases/****>
yarn install --check-files
はyarn.lock
と「インストールされている内容」に差異があった場合、バージョンを合わせるためのインストールをおこなってくれます。
Verifies that already installed files in node_modules did not get removed.
Yarn公式
少し話はそれましたが、Rails.root
を確認すると、/var/www/$APP_NAME/releases/****
と全く異なるパスを指定してますね。そりゃ、起動できないわって感じですね。
というわけで修正を行います。
bind "unix:///var/www/$APP_NAME/shared/tmp/sockets/puma.sock"
これでようやくアプリが表示されるかなとアクセスしてみると...
なぜか表示されません!!!
正直、発狂しましたよ。
色々調べた結果、ある仮説に辿り着きます。
そういえばpumaの設定ファイルもう一つあったな、と。
早速見に行くことにしましょう。
$ cat /etc/systemd/system/puma_$APP_NAME_production.service
[Unit]
Description=Puma HTTP Server for $APP_NAME (production)
After=network.target
[Service]
Type=simple
User=****
WorkingDirectory=/var/www/$APP_NAME/current
# Support older bundler versions where file descriptors weren't kept
# See https://github.com/rubygems/rubygems/issues/3254
ExecStart=/home/user
ExecReload=/bin/kill -USR1 $MAINPID
StandardOutput=append:/var/www/$APP_NAME/shared/log/puma_access.log
StandardError=append:/var/www/$APP_NAME/shared/log/puma_error.log
Restart=always
RestartSec=1
SyslogIdentifier=puma
[Install]
WantedBy=multi-user.target
特に起動コマンドExecStart
に注目してほしい。
pumaが起動するのはpuma.sock
を使って起動するはず。
パスが間違っている!
なので、パスを編集しました。
# サーバのルートディレクトリから
$ cd /etc/systemd/system/
# ${APP_NAME}の箇所は自分のアプリ名に変えてVimを開く
$ vi puma_${APP_NAME}_production.service
# 設定ファイルの再読込
$ sudo systemctl daemon-reload
# サービス自動起動有効
$ sudo systemctl enable puma_${APP_NAME}_production.service
Vimが開けたら修正します。
ExecStart=/home/ユーザ名/.rbenv/bin/rbenv exec bundle exec --keep-file-descriptors puma -C /var/www/$APP_NAME/shared/puma.rb
修正ができたら以下を実行します。
# サーバのルートディレクトリから
$ cd /etc/nginx
# nginxの再起動
$ sudo service nginx restart
Redirecting to /bin/systemctl restart nginx.service
これにてようやくアプリを表示することができました。
お疲れ様です。
最後までお読みいただきありがとうございます。