なぜこの記事を書いたか?
Laravelの場合、ローカル環境ではphp artisan serveのような簡易サーバを使えば画面が見えます。しかし、本番環境の場合こんなに簡単ではないです。
初心者の自分としては意外とサーバ構築が複雑だったので、一回クライアントからのリクエストがあった際に画面が見えるまでの仕組みをきちんと理解しておこうと思い、本記事を書きました。
本記事では省略しているルートテーブルやNATゲートウェイ、セキュリティグループなどまだ色々設定することはありますが、今回の目的はリクエストの流れを簡潔に追うことにしたいので、大まかな流れの説明をしようと思います。
(Laravelに関連して、本番環境のデプロイでcorsエラーと戦った記録:
https://qiita.com/tryuuu/items/c6969b00e24b3a0a4914)
使用技術
バックエンド
Laravel(11.x)
フロントエンド
Vue.js
サーバサイド
Docker, ECS on Fargate, ALB, nginx
データベース
RDS
ファイル構成
Laravelをサーバにデプロイする際のよく見かけるような構成です。
フロントページの表示にVue.jsを使っているので、nginx/Dockerfileにおいてnpm run buildを行い、生成された静的ファイルをLaravelのpublic配下に配置するようにしています。この状態のイメージをECRに登録します。
php/Dockerfileの方も同じようにビルドしてイメージをECRに登録します。
これらのイメージをECSのタスク定義において参照することで使用します。
サーバ構成
以下のような構成になります。
リクエストの流れ
エンドユーザからのリクエストがあったときの大まかな流れとしては、
-
インターネットゲートウェイを通じてVPC外からのリクエストをVPC内に通す
-
ロードバランサー(HTTPの場合ポート80、HTTPSの場合ポート443)によるリクエストの分散→ECS on Fargateで実行されているサービス(nginxコンテナ)にリクエストを転送
-
nginxコンテナ(ポート80)でリクエストを受け取り、ビルドされpublic配下に置かれている静的ファイル(Vue.js)をレスポンスとして返し、画面を表示する(nginxは元々静的ファイルの配信が得意)
-
動的処理(Laravel)が必要な部分はnginxからphpコンテナ(ポート9000)にリクエストを転送(nginxがリバースプロキシとして機能)
-
php-fpmによりphpの実行を行い動的な処理を行う
-
生成されたコンテンツをnginxを通じてクライアントに伝送
ざっと図で上記の説明を補足するとVPC内部はこのような処理になります。
(参考: https://cloudonaut.io/how-to-dockerize-your-php-application-for-aws-fargate/)
(補足)nginxとphp-fpmコンテナ間の通信
ECS on Fargateで同じタスク内に二つのコンテナがある場合、localhostで通信することができます。
nginxはリバースプロキシとして機能し、動的な処理が必要なリクエストはphpコンテナに転送します。nginxにはphpのモジュールがないためです。
従って、nginxはphp-fpmに対してphpの実行を依頼する、という形式を取るわけです。
この際、nginxとphpコンテナ間の通信では、FastCGIのインターフェースであるphp-fpmへリクエストを転送します。phpファイルをFastCGI(php-fpm)で接続するように設定するなどの操作をnginx/*.confで記述します。
一例として、
fastcgi_pass localhost:9000;
といった記述は、nginxがphpファイルの実行をFastCGIサーバに委ね、localhost:9000で9000番ポートでリッスンしているphp-fpmに接続をする、という意味です。
(参考: https://www.spiceworks.co.jp/blog/?p=12317)
まとめなど
結構個人的にはこのようなサーバ構築においては、一度で全部理解しようとするのではなく(天才を除き)、まず大まかな流れをきちんと把握してから細かいところを詰めていく、という勉強の仕方が良いのではないかと思っています。
今後は監視・CI/CDパイプラインの作成を行なっていきたいと思っています。
ここまで読んでくれた方、ありがとうございました。