以前Apollo GraphQLに入門してみた記事を書きましたが、勉強は終わったのでReactアプリ用バックエンドを作りはじめました。
バックエンドにはいくつかの機能があり、nginxのリバースプロキシを前段に入れる事にしました。nginxはリバースプロキシに良く使われているので設定ファイルは簡単に書けると思っていましたが、半日もかかってしまいました。😅
バックエンドの構成
今回のバックエンドは、Reactアプリ向けのサービスを提供する(GraphQL)APIサーバーと、ユーザーやデータの管理を行う管理画面Webアプリの2つの機能があります。データやユーザー管理情報等はPostgreSQLのデーターベースに格納しています。
そして、APIサーバー、管理画面は別のDocker Contenerで動きます。データーベースのPostgreSQLは開発環境ではDocker Contener、本番環境ではAmazon RDSを使い、コンテナーの構成管理はDocker Composeでおこなっています。
ただし当面は、管理画面Webアプリは作らずにデーターベースのメンテナンス用にpgAdminを使う事にしました。
初期の開発環境では上の図のようにAPI/管理画面は、別ポートでアクセスしていましたが、通信のSSL化やサーバーの設定等を考えると両方とも標準の80(HTTPS時は443)ポートで動かした方が良さそうです。そしてパス名の先頭で両サービスを分けられる用にnginxのリバースプロキシを入れる事にしました。
http://server/api/
、https://server/api
へのアクセスならhttp://localhost:5000
のAPIサーバーに接続http://server/admin/
、https://server/admin
へのアクセスならhttp://localhost:5001
の管理画面Webアプリに接続
nginxのリバースプロキシ用設定
さてnginxの設定ファイルですが、APIサーバーはGraphQLなので固定URLへのシンプルなHTTP通信のみなので、ネット上の情報に良く書かれている
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/ {
proxy_pass http://server:5000/graphql/;
}
location /pgadmin/ {
proxy_pass http://pg_admin:5001/;
}
}
で動きましたが、pgAdminは上手く行きませんでした。😞
pgAdminはWebアプリなので、別パスにあるCSSやJavaScript、画像なを配信する必要がありますし、ログインページにリダイレクトしたりします。
リダイレクト
pgAdminにアクセスすると、ログインページ /login?.....
にリダイレクトしますが、ブラウザーには /admin/login?.....
パスを送らないといけません。このへんはproxy_redirect
で設定できるようですが、いろいろな記事を参考にしてみましたが上手くいきませんでした。
そんな時 Reverse Proxying to pgAdminという記事を見つけ、参考にしながら書いたところ動くようになりました。
しかし、よくよく見るとpgAminのドキュメントの下の方にも同じ設定が書かれていました。😅
80(443)以外のポート
しかし、開発環境では http://localhost:8080
でnginxが動作するのですが、うまく8080ポートをアクセスしてくれません。
設定ファイルに、proxy_set_header Host $host;
と書きホスト名をpgAdminに転送しますが、ポート番号は転送されないそうです、proxy_set_header Host $http_host;
と書くとホスト名とポート番号が転送されるようになります。
最終的なnginxの設定ファイル
最終的なnginxの設定ファイルは、以下のようになりました。
server {
listen 80;
listen [::]:80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /api/ {
proxy_pass http://server:5000/graphql/;
proxy_set_header Host $http_host;
}
location /pgadmin/ {
proxy_set_header X-Script-Name /pgadmin;
proxy_set_header Host $http_host;
proxy_pass http://pg_admin:5001/;
proxy_redirect off;
}
}
めでたしめでたし😊