
Laravel + Inertia (React/Vue) の組み合わせは、SPA(シングルページアプリケーション)の体験とサーバーサイド(Laravel)の書きやすさを両立できる、非常に強力な構成です。
しかし、ローカルのDocker Compose環境では問題なく動作しても、AWSのECS Fargateのような本番環境にデプロイしようとすると、いくつかの疑問に直面します。
- 「NginxとPHP-FPMコンテナはどう連携させるのがベスト?」
- 「fastcgi_passってローカルと設定を変える必要ある?」
- 「InertiaでビルドしたReactのJS/CSSファイルは、結局どのコンテナに置くのが正解?」
この記事では、fastcgi_pass の基本から、ECS Fargateでの最適なコンテナ構成、そしてInertia/Reactプロジェクト特有の「静的ファイルの配置場所」問題までを、順を追って解説します。
fastcgi_pass とは?
NginxとPHP-FPMの「橋渡し」
まず基本のおさらいです。Nginxは高性能なWebサーバーですが、それ自体はPHPコードを実行できません。
一方、PHP-FPMはPHPコードを実行することに特化したプロセス(サーバー)です。
Nginxがクライアント(ブラウザ)から .php ファイルへのリクエストを受け取ったとき、そのリクエストをPHP-FPMに処理してもらう必要があります。
このとき、Nginxの設定ファイル(nginx.conf)で、「どのPHP-FPMに処理を依頼するか」の宛先を指定するのが fastcgi_pass ディレクティブです。
location ~ \.php$ {
    # ...
    # ↓ この一行が「橋渡し」の指定
    fastcgi_pass php-fpm-server:9000; 
}
ローカル開発 (Docker Compose) での構成
ローカル開発では、「1コンテナ1責務」の原則に従い、NginxとPHP-FPMを別々のコンテナとして docker-compose.yml で定義するのが一般的です。
# docker-compose.yml (抜粋)
version: '3'
services:
  # Nginxコンテナ
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - ./laravel-project:/var/www/html
  # PHP-FPMコンテナ
  php:
    build: . # PHP-FPMとLaravelコードを含むDockerfile
    volumes:
      - ./laravel-project:/var/www/html
この構成では、NginxコンテナとPHPコンテナは 別々のネットワーク空間 に存在します。Docker Composeが提供する内部ネットワークを介して、サービス名で通信します。
したがって、NginxコンテナからPHPコンテナへは、php というサービス名(ホスト名)を使ってアクセスします。
# nginx.conf (Docker Compose用)
location ~ \.php$ {
    # ...
    # 'php' サービス(コンテナ)の 9000番ポートに転送
    fastcgi_pass php:9000;
}
(※ このTCP/IP通信によるパフォーマンスやセキュリティの懸念は、コンテナ間通信がDockerの内部ネットワークに限定されていれば、実用上ほとんど問題になりません。)
【1タスク2コンテナ】本番 (ECS Fargate) での構成:
さて、本題のECS Fargateです。
ECSでは、docker-compose.yml に相当するものとして「タスク定義 (Task Definition)」を使います。
ここで重要なキーポイントは、「1つのタスク定義の中で、NginxコンテナとPHP-FPMコンテナの2つを定義する」ことです。
これら2つのコンテナは、1セットで「Webアプリケーションサーバー」として機能します。
ECS Fargateでのfastcgi_passはどうなる?
ECSの同一タスク内で実行されるコンテナは、同じネットワーク空間(ネットワークモード awsvpc)を共有します。
これは、Nginxコンテナから見ると、PHP-FPMコンテナが「他人」ではなく、「自分自身(localhost)」として見えることを意味します。
したがって、ECS Fargate用のNginxイメージに含める nginx.conf の設定は、以下のようになります。
# nginx.conf (ECS Fargate用)
location ~ \.php$ {
    # ...
    # サービス名ではなく、localhost (127.0.0.1) を指定する
    fastcgi_pass 127.0.0.1:9000;
}
タスク定義のイメージ
タスク定義では、以下のように設定します。
- コンテナ-A: php-fpm-container- イメージ: (Laravelコードを含むPHP-FPMイメージ)
- ポートマッピング: なし (外部に公開する必要はないため)
 
- コンテナ-B: nginx-container- イメージ: (設定済みのnginx.confと静的ファイルを含むNginxイメージ)
- ポートマッピング: 80:80(ALBからのトラフィックを受け取るため)
 
ALB(ロードバランサー)からのトラフィックはNginxコンテナが受け取り、必要に応じて localhost:9000 を介してPHP-FPMコンテナに処理を渡します。
Inertia/Reactのビルドファイルはどこに置く?
ここで、Inertia/React構成特有の問題に直面します。
「InertiaはLaravel(PHP)がビューを配信する仕組みだから、npm run build で生成された public/build フォルダは、PHP-FPMコンテナにだけ置けば良いのでは?」
これはよくある誤解ですが、パフォーマンスと責務分離の観点から、ビルドした静的ファイル(JS/CSS)はNginxコンテナに配置するのが正解です。
この理由を理解するために、Inertiaのページが読み込まれる2段階のフローを見てみましょう。
ステップ1: HTMLシェルのリクエスト (PHP-FPMが処理)
- ブラウザが https://example.com/dashboardにアクセスします。
- ALB → Nginxコンテナがリクエストを受け取ります。
- NginxはこれがPHPのリクエストだと判断し、fastcgi_pass 127.0.0.1:9000を使ってPHP-FPMコンテナに転送します。
- PHP (Laravel) が起動し、Inertiaは app.blade.phpをレンダリングしようとします。
- このとき、PHPは public/build/manifest.jsonを読み取り、HTMLに含めるべきJS/CSSのファイル名を特定します。
- PHPは以下のようなHTMLの「ガワ」を生成し、Nginx経由でブラウザに返します。
<html> <head> <script src="/build/assets/app.12345.js" defer></script> <link rel="stylesheet" href="/build/assets/app.67890.css"> </head> <body> <div id="app" data-page="..."></div> </body> </html>
ステップ2: 静的アセット(JS/CSS)のリクエスト (Nginxが処理)
- ブラウザは、ステップ1で受け取ったHTMLを解析します。
- 「/build/assets/app.12345.jsと/build/assets/app.67890.cssが必要だ」と判断し、ブラウザは別途2回のリクエストをサーバーに送信します。
- このリクエストは、もはやPHPとは全く関係ありません。
- ALB → Nginxコンテナがこの2つのリクエストを受け取ります。
- Nginxは「自分の管理下(publicフォルダ)にそのファイルがあるか?」を探します。
- Nginxコンテナに public/build/以下の実体ファイルが存在するため、NginxはPHP-FPMを起動することなく、それらの静的ファイルを超高速でブラウザに直接返します。
もし、NginxコンテナにJS/CSSファイルがなければ、このリクエストもPHP-FPMに転送されてしまい、「JSファイルを取得するためだけにLaravelを起動する」という深刻なパフォーマンスボトルネックが発生します。
CI/CDでのベストプラクティス
上記2ステップから、CI/CDパイプラインでDockerイメージをビルドする際は、以下の構成が最適です。
- npm run buildを実行し、- public/buildディレクトリを生成します。
- PHP-FPMイメージのビルド:
- Laravelのコード(app/,routes/など)をコピーします。
- ステップ1のために public/build/manifest.jsonをコピーします。(リンク生成に必要)
 
- Laravelのコード(
- Nginxイメージのビルド:
- nginx.confをコピーします。
- ステップ2のために publicフォルダ全体(index.phpと、public/build以下の 全てのJS/CSSファイル を含む)をコピーします。(静的アセットの配信用)
 
結論
manifest.json はPHP-FPMコンテナに、JS/CSSの実体ファイルはNginxコンテナに必要です。
両方のイメージに public フォルダ(または public/build)全体をコピーするのが、最もシンプルで確実な方法です。
まとめ
ECS Fargateで Laravel + Inertia + React 構成を動かすための要点をまとめます。
- 構成: 「1タスク2コンテナ(Nginx + PHP-FPM)」構成を採用します。
- fastcgi_pass: NginxからPHP-FPMへの通信は、同一タスク内のため- fastcgi_pass 127.0.0.1:9000;を指定します。
- 静的ファイル: ビルドしたJS/CSSは、パフォーマンス最適化のためNginxコンテナに配置し、Nginxから直接配信させます。
- manifest.json: HTMLシェル生成のため、PHP-FPMコンテナにも- manifest.jsonが必要です。
この構成により、PHP-FPMは動的処理に専念し、Nginxは静的ファイルの高速配信に専念するという、「1コンテナ1責務」のメリットを最大限に活かした、スケーラブルな本番環境を構築できます。




 
                         
                         
                         
                        