Bad Gatewayの原因
そもそもBad Gateway*はどういったときに出るのか調べてみると、
nginxにリクエストは届いているが、unicornとの連携がうまくいっていない場合に起きるようです。
多くの場合はunicorn socketのパス記入ミスなどが原因ですが、自分はかなりここでハマってしまったので解決策をまとめました。
構成
ALB + nginx + unicornで構成し、webアプリケーションはRuby On Rails を使用。
インフラはAWSでVPC内に一つのEC2を使っています。
1. エラーログの表示
まずはnignxでエラーを表示しましょう。
自作のconfファイルを使用していない場合であれば/var/log/nginx/error.logに格納されているのでそちらを表示。
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log; ←こちら
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/
*.conf;
自作ファイルでパスを指定している場合は置き換えて対応して下さい。
$ tail -100 /var/log/nginx/error.log
2021/03/26 10:09:45 [error] 30256#0: *9 connect() to unix:/var/www/my_app/shared/tmp/sockets/unicorn.sock failed (111: Connection refused) while connecting to upstream…
(2: No such file or directory)が出る場合
socketファイルが生成されていないため起きているエラーです。
なるほどじゃあ作成すればいいのかとtouchコマンドで生成すると…
ArgumentError: socket=/var/www/my_app/shared/tmp/sockets/unicorn.sock specified but it is not a socket!
怒られてしまうので注意です。
sockファイルはunicorn起動時に自動的に生成されるもので、単に作成したものではsockファイルとして認識されません。
なのでsockファイルがない状態でbundle exec unicorn_rails -c config/unicorn.rb -D -E productionコマンドでunicornを再起動しましょう。
$ rm /var/www/my_app/shared/tmp/sockets/unicorn.sock
$ bundle exec unicorn_rails -c config/unicorn.rb -D -E production
(13: Permission denied)が出る場合
unicornを起動するのに必要なファイルが権限不足で読み取れていない状態です。
一度www配下に777権限を与えて正常に起動するかを見てみて下さい。
$ sudo chmod 777 /var/www
もう一度アクセスしてみてください。
(111: Connection refused) が出る場合
socketパスが間違っている
unicornへの通信が拒否されています。
多くの場合はsocketパスが間違っていて正しく連携できていないことが原因ですのでパスをコピペしてnginxをリロードします。
ローカル側
(省略)
listen "/var/www/my_app/shared/tmp/sockets/unicorn.sock"
EC2側
upstream unicorn {
server unix:/var/www/my_app/shared/tmp/sockets/unicorn.sock; ←ここを統一
}
server {
listen 80;
server_name ELASTIC IPかドメイン;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
(省略)
unicornが起動していない場合
unicorn自体が起動していない場合にも連携失敗でこのエラーが出ます。
$ ps aux | grep unicorn
ec2-user 3542 0.0 0.0 119420 920 pts/1 S+ 00:09 0:00 grep --color=auto unicorn
masterが起動していないのでコマンドで再起動
↓
$ cd /var/www/my_app/current
$ bundle exec unicorn_rails -c config/unicorn.rb -D -E production
ec2-user 3579 38.0 11.1 439708 112612 ? S 00:10 0:02 unicorn_rails master -c config/unicorn.rb -D -E production
ec2-user 3580 0.2 9.8 439708 98708 ? S 00:10 0:00 unicorn_rails worker[0] -c config/unicorn.rb -D -E production
ec2-user 3581 0.0 9.6 439708 97120 ? S 00:10 0:00 unicorn_rails worker[1] -c config/unicorn.rb -D -E production
ec2-user 3582 0.0 9.6 439708 97124 ? S 00:10 0:00 unicorn_rails worker[2] -c config/unicorn.rb -D -E production
ec2-user 3584 0.0 0.0 119420 928 pts/1 S+ 00:10 0:00 grep --color=auto unicorn
-c config/unicorn.rb -D -E productionでプロセスが起動していることが分かります。
その他は考えられる原因がいくつかあるのでこちらを参考にしてみて下さい。
>> 終わりなき (111: Connection refused) との闘い
正直このエラーが一番厄介な気がします…
最後に
プログラムのエラーに比べてサーバーエラーは直感で理解できない部分が多く、前提知識が全くない状態だと太刀打ちできないので難易度が格段に高く見えます…
自分もここでハマって5~7日近くかかってしまったこともありましたので、少しでもnginxエラーで悩む方が少なくなればいいなと思いこちらの記事を投稿しました。