Nginx on Dockerでリバースプロキシが動かない時のチェックリスト

2024/07/01に公開

Dockerでアプリケーションサーバー(Node.js)のコンテナを立てて、Nginxのコンテナからリバースプロキシしようとして、かなりハマったので、その時の体験と解決方法を共有します。

何をやりたかったのか

  • DockerNginxNode.js(アプリケーションサーバー)のコンテナを建てていた。
  • Node.jsへのリクエスト前にNginxを置き、リクエストをリバースプロキシさせたい。

発生していたエラー

  • Nginxから指定しているホスト(アプリケーションサーバー)に接続できないというエラー
no live upstreams while connecting to upstream, client: 192.168.144.1, server: localhost, request: "GET /api/ HTTP/1.1", upstream: "http://localhost/api/health", host: "localhost"

上手く行かない時にどんな状態だったか

  • アプリケーションサーバー(Node.js)は起動している
curl http://localhost:4000/api/health
{"status":"ok","response":{"now":"2024-06-28T09:46:03.360Z"}}%
  • Nginxからproxy_passに設定すると、502 Bad Gatewayになる。
location /api/ {
    proxy_pass http://localhost:4000/api/; -> 502 Bad Gateway
    proxy_http_version 1.1;
    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;
}
  • nginx -tでconfigを構文チェックをしても設定ファイル上ではエラーは起こっていない。
docker exec -it nginx bash
root@:/# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

結論

  • Dockerのネットワーク機能を利用する
    Dockerコンテナ間(今回のケースではNginxNode.js)でlocalhostの通信はできないため、Dockerのネットワーク内で通信する(コンテナ名を指定するなどが)必要があります。

もし、通信したいコンテナ同士のdocker-compose.ymlが分かれている場合は、同一のネットワークであること明示的に指定(networkオプション)を記載します。

location /api/ {
    proxy_pass http://{Container_name}:4000/api/;  # コンテナ名を指定する
    proxy_http_version 1.1;
    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;
}

まとめ

  • Stack Overflowなどでエラーメッセージを検索しまくりましたが、一向に解決策が見つからず頭を抱えていました。なんとなくNginxのコンテナの中に入り、curl http://localhost:4000を叩いた瞬間に気づきました。Nginxのエラーを調べまくっていましたが、Docker上で動かしていることに意識が向いていなかったのが原因ですね。
  • もし、Docker上でNginxのコンテナから別のDockerコンテナに対して接続を行いたい場合は、Dockerネットワークを正しく設定しているか確認することを強くお勧めします...

この方法が皆さんの参考になれば幸いです。
最後に、Nginx on Dockerでリバースプロキシがうまく動作しない場合のチェックリストを記載して記事を締めます。

チェックリスト

✅ リバースプロキシするサーバーは起動しているか?コンテナ外からcurlコマンドなどで通信を確認できるか?
✅ configファイルに記載しているポートやホストに間違いがないか?
nginx -tでconfigを構文チェックをしても設定ファイル上ではエラーは起こっていないか?
✅ Dockerコンテナ間での通信には、localhost127.0.0.1ではなく、コンテナ名やDockerネットワークを使用しているか?
docker-compose.ymlが使用されている場合、適切なネットワーク設定がされているか?特に、異なるコンテナが同じネットワーク上にあることを確認しているか?
proxy_passのURLが正しく設定されているか?特に、末尾のスラッシュ(/)の有無が意図した通りになっているか?
✅ Nginxのログを確認して、リバースプロキシの試みがどのように失敗しているか、具体的なエラーメッセージを確認しているか?
✅ セキュリティグループやファイアウォールの設定が、コンテナ間通信を妨げていないか?

Discussion