Nginx 502 Bad Gatewayの3つの原因と実践的な解決手順

Nginxで502 Bad Gatewayエラーが発生する場合、アップストリームサーバーへの通信失敗が原因です。この記事では、エラーログの読み方から具体的な解決手順まで、本番環境ですぐに使える診断方法と対策を紹介します。

502 Bad Gatewayが発生する3つの主な原因

原因1: アップストリームサーバーがダウンまたは応答がない

最も一般的な原因は、バックエンドのアプリケーションサーバー(Express、Django、Unicornなど)が起動していないか、ポート番号が間違っている場合です。Nginxがリクエストを転送しようとしたときに接続できないため、502エラーが返されます。

確認コマンド:

# アップストリームサーバーの状態確認(例:127.0.0.1:3000)
netstat -tlnp | grep 3000

# または
ss -tlnp | grep 3000

# ポートが開いているか確認
curl -v http://127.0.0.1:3000/

原因2: Nginxの設定ミス(upstreamブロックの誤設定)

nginx.confまたはサイト設定ファイルでアップストリームサーバーのアドレスやポートを間違って指定している場合、Nginxは接続できず502エラーが返されます。

設定ファイルの確認:

# Nginx設定の構文チェック
nginx -t

# 設定ファイルの内容確認
cat /etc/nginx/nginx.conf
cat /etc/nginx/sites-enabled/default  # またはあなたのサイト設定

原因3: アップストリームサーバーのタイムアウトまたはクラッシュ

アプリケーションが処理に時間がかかるか、メモリ不足でクラッシュしている場合、Nginxはタイムアウトして502エラーを返します。また、アプリケーションのエラーログに大量のエラーが出ていることがあります。

実践的な診断と解決手順

ステップ1: Nginxのエラーログを確認する

まずはNginxのエラーログを確認し、具体的なエラーメッセージを把握します。

# エラーログの末尾を表示
tail -50 /var/log/nginx/error.log

# リアルタイムでログを監視
tail -f /var/log/nginx/error.log

# 502に関連するエラーのみを抽出
grep "502\|upstream" /var/log/nginx/error.log | tail -20

エラーログには以下のようなメッセージが表示されます:

  • connect() failed (111: Connection refused) → アップストリームサーバーが起動していない
  • upstream timed out (110: Connection timed out) → サーバーが応答遅い、またはタイムアウト設定が短い
  • no live upstreams → すべてのアップストリームサーバーがダウンしている

ステップ2: アップストリームサーバーの健全性をテストする

Nginxサーバーからアップストリームサーバーに直接接続可能か確認します。

# アップストリームサーバーのレスポンスを確認
curl -v http://localhost:3000/health

# ヘッダーのみを取得
curl -I http://localhost:3000/

# タイムアウトを指定してテスト
curl --max-time 5 -v http://localhost:3000/

# ソケットレベルでの接続確認
timeout 3 bash -c "echo > /dev/tcp/127.0.0.1/3000" && echo "Connection OK" || echo "Connection FAILED"

ステップ3: Nginx設定ファイルを検査する

以下は一般的なNginx設定例です。あなたの設定ファイル(/etc/nginx/sites-enabled/defaultなど)と比較してください。

upstream backend {
    # アップストリームサーバーの指定
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    
    # タイムアウト設定(デフォルト60秒)
    keepalive 32;
}

server {
    listen 80;
    server_name example.com;

    location / {
        # upstreamの名前を指定
        proxy_pass http://backend;
        
        # 重要: Hoストヘッダーを転送
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # タイムアウト設定を明示的に指定(秒単位)
        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
    }
}

設定を変更した後は必ず構文チェックとリロードを実行します:

# 構文チェック
sudo nginx -t

# 設定のリロード(グレースフルリスタート)
sudo systemctl reload nginx

# または
sudo service nginx reload

ステップ4: プロセスとリソースを確認する

アップストリームサーバー(Node.jsやPythonなど)が実際に起動しているか確認します。

# Node.jsプロセスの確認
ps aux | grep node

# ポート使用状況の確認
lsof -i :3000

# リソース使用状況(メモリ不足がないか確認)
free -h
df -h

# アップストリームサーバーのログを確認
journalctl -u myapp -n 50  # systemdで管理している場合
tail -50 /var/log/myapp.log

ハマりポイント: proxy_set_headerを忘れずに設定する

Nginxのデフォルト設定ではHostヘッダーなどが転送されないため、アプリケーション側で問題が発生することがあります。以下のヘッダーは必ず設定してください:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

すぐに試せる総合的な設定例

以下は本番環境で推奨される設定例です。このファイルを/etc/nginx/sites-available/mysiteに保存し、シンボリックリンクを作成してください。

upstream app_backend {
    # 複数のバックエンドサーバーを指定(負荷分散)
    server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
    
    # サーバーがダウンした場合に他のサーバーにフェイルオーバー
    # max_fails: 何回失敗したらサーバーをダウンと判定するか
    # fail_timeout: ダウンと判定してから何秒待つか
}

server {
    listen 80;
    server_name example.com www.example.com;

    # ログ設定
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    location / {
        proxy_pass http://app_backend;
        
        # ホストヘッダーとクライアント情報を転送
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # タイムアウト設定(秒単位)
        proxy_connect_timeout 10s;   # 接続待機時間
        proxy_send_timeout 30s;      # リクエスト送信待機時間
        proxy_read_timeout 30s;      # レスポンス受信待機時間
        
        # バッファリング設定(大容量ファイル対応)
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        
        # キープアライブ設定
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }

    # ヘルスチェック用エンドポイント
    location /health {
        access_log off;
        proxy_pass http://app_backend;
        proxy_connect_timeout 5s;
        proxy_read_timeout 5s;
    }
}

設定をシステムに反映します:

# 設定ファイルをsites-enabledにリンク
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite

# デフォルト設定を無効化(必要に応じて)
sudo rm /etc/nginx/sites-enabled/default

# 構文チェック
sudo nginx -t

# Nginxをリロード
sudo systemctl reload nginx

502エラーが解決しない場合のトラブルシューティング

ファイアウォール設定を確認する

Nginxとアップストリームサーバーが同じサーバー上にない場合、ファイアウォールが通信をブロックしている可能性があります:

# UFWを使用している場合
sudo ufw allow 3000

# iptablesを使用している場合
sudo iptables -A INPUT -p tcp --dport 3000 -j ACCEPT

# 接続確認(別サーバーから)
telnet backend-server-ip 3000

アップストリームサーバーのリソース確認

メモリ不足やCPU不足でアプリケーションがクラッシュしていることがあります:

# メモリ使用率が高いプロセスを表示
ps aux --sort=-%mem | head -10

# CPUスパイクを確認
top -b -n 1 | head -20

# Dockerを使用している場合
docker stats

Nginxのキャッシュをクリアする

502エラーがキャッシュされている可能性があります:

# アクセスログからキャッシュの有無を確認
tail -50 /var/log/nginx/access.log | grep "HIT\|MISS"

# Nginxのキャッシュをクリア(設定されている場合)
sudo rm -rf /var/cache/nginx/*

# Nginxをリロード
sudo systemctl reload nginx

使うべき場面と使うべきでない場面

Nginxのリバースプロキシを使うべき場面:

  • 複数のアプリケーションサーバーに対して負荷分散したい
  • HTTPSターミネーションを集約したい
  • セキュリティ上の理由でアプリケーションサーバーを直接公開したくない
  • スタティックファイル配信を高速化したい

Nginxを使うべきでない場面:

  • シンプルなスタンドアロンアプリケーション(複雑さが増す)
  • 開発環境(セットアップの手間が増える)
  • 特定の言語のアプリケーションサーバー(Flask、Express)が既にそれらの機能を持っている場合

類似ツールとの比較

Nginxとその他のリバースプロキシ:

  • Apache:リバースプロキシ機能は持つが、Nginxより消費メモリが多い
  • Caddy:自動HTTPS化が便利だが、プロダクション環境ではNginxの方が実績が豊富
  • HAProxy:ロードバランシングに特化しており、複雑な負荷分散設定に向いている

よくある質問

Q: 502エラーが断続的に発生します。原因は何ですか?

A: 断続的な502は、アプリケーションサーバーがたまに落ちている、またはメモリリークで徐々に遅くなっ

K
AWS・Python・生成AIを専門とするソフトウェアエンジニア。AI・クラウド・開発ワークフローの実践ガイドを執筆しています。詳しく見る →