🍏

【入門】 Nginx + PHP-FPM の仕組み

2025/02/09に公開

本記事では、PHP-FPM を初めて学ぶ方に向けて、Nginxとの連携や設定の基本を解説します🚀

PHP-FPMとは? 🤔

PHP-FPM(FastCGI Process Manager)は、PHPの処理を最適化するためのプロセスマネージャーです。Nginx は PHP を直接処理できないため、PHP-FPM が FastCGI というプロトコルを利用して Nginx と PHP の橋渡しを行います。

⚡ FastCGIとは?

FastCGI とは、Webサーバーとアプリケーションの間で高速な通信を実現するプロトコルです。従来のCGIとは異なり、リクエストごとにプロセスを作成・破棄するのではなく、プロセスを維持しながら複数のリクエストを効率的に処理できます。

以下のような構成でNginxとPHP-FPMが連携し、リクエストが処理されます。

🗣️ シーケンス図の説明

  1. クライアント(ブラウザやAPIリクエスト)がNginxにHTTPリクエストを送信
  2. Nginx がリクエストを受け取り、静的ファイル(HTML, CSS, JSなど)はそのまま返す
  3. PHPスクリプトの場合、NginxはFastCGIを通じてPHP-FPMにリクエストを転送
  4. PHP-FPMがスクリプトを実行し、結果をNginxに返す
  5. Nginx がPHPの実行結果をクライアントにレスポンスとして返す

PHP-FPMのプールとは? 🏊‍♂️

PHP-FPM は「プール」という単位でプロセスを管理します。プールごとに同時接続数やプロセスの数を指定でき、プロセスやソケットは別のものを使います。使用するPHPアプリケーションごとにPHP-FPMのプールを作り、使用する資源を分けるといった使い方ができます🙆‍♀️

🏊‍♀️ プールの主な構成要素

  1. マスター・プロセス:設定を読み込み、ワーカープロセスを管理する
  2. ワーカープロセス:実際にPHPスクリプトを処理する
  3. リスナー(ソケット):Webサーバーとの通信を管理する

デフォルトでは www という名前のプールが作成されますが、用途に応じて追加・変更できます。

PHP-FPM の設定ファイル 🛠

Nginxをインストール後、PHP と PHP-FPM を導入(yum install php php-fpm)すると、以下のような設定ファイルが作成されます。

/etc                         # 設定ファイルのディレクトリ
├── php.ini                  # PHP の基本的な設定を記述するファイル
├── php-fpm.conf             # PHP-FPM のメイン設定ファイル
├── php-fpm.d/               
│   ├── www.conf             # プール設定ファイル    

動作環境のOSは、 Amazon Linux 2023 です。
参考:🔗 2024年版 - AWSのEC2にPHP+Nginx+phpMyAdminの環境を構築する

1️⃣ php-fpm.conf の概要

php-fpm.conf は、PHP-FPM のメインの設定ファイルです。PHP-FPM の動作設定などが含まれます。

以下は PHP-FPM の php-fpm.conf の初期設定値です。(初期設定でコメントアウトされているコードは省略しています。)

php-fpm.conf
include=/etc/php-fpm.d/*.conf
[global]
pid = /run/php-fpm/php-fpm.pid             # プロセス ID を格納するファイルのパス
error_log = /var/log/php-fpm/error.log     # エラーログファイルのパス
daemonize = yes                            # デーモンとして実行するかどうか

2️⃣ /etc/php-fpm.d/*.conf の概要

このディレクトリには、PHP-FPM の設定を分割して管理するための設定ファイルが「プール」単位で格納されています。デフォルトでは、www.confというプール設定ファイルが生成されています。

以下は www.confファイルの設定例です。(初期値を一部変更しています)

www.conf
[www]                             # プールの名前
user = nginx                      # プールを実行するユーザー名
group = nginx                     # プールを実行するグループ名

listen = /run/php-fpm/php-fpm.sock  # リッスンソケットのパス
listen.owner = nginx                # ソケットファイルの所有者
listen.group = nginx                # ソケットファイルのグループ
listen.allowed_clients = 127.0.0.1  # アクセスを許可するクライアントのIPアドレス (localhost のみ許可)

pm = dynamic                      # プロセスマネージャーの動作モード (動的にプロセス数を調整)
pm.max_children = 50              # 最大ワーカープロセス数
pm.start_servers = 5              # 起動時のワーカープロセス数
pm.min_spare_servers = 5          # 最小アイドルワーカープロセス数
pm.max_spare_servers = 35         # 最大アイドルワーカープロセス数
pm.status_path = /status             # PHP-FPM のステータス情報を取得できるパス

slowlog = /var/log/php-fpm/www-slow.log    # スローリクエストのログファイルパス
php_admin_value[error_log] = /var/log/php-fpm/www-error.log # PHP エラーログファイルパス

php_admin_flag[log_errors] = on           # PHP エラーログを有効にする
php_value[session.save_handler] = files   # セッションハンドラーを files に設定 (ファイルベースセッション)
php_value[session.save_path]    = /var/lib/php/session  # セッションファイルの保存パス
php_value[soap.wsdl_cache_dir]  = /var/lib/php/wsdlcache   # SOAP WSDL キャッシュディレクトリ

📌 ポイント

  • プールを実行するusergroupの値はnginxを設定しています。
    • PHP-FPM の プロセスは Nginx と同じユーザーの権限で動作します。PHPプログラムとNginx の権限の違いによるトラブルを避けるために、Nginx が使用するユーザーと同じユーザーで PHP-FPM を実行することが一般的です。
  • listenでは Nginx が PHP-FPM と通信するためのソケットファイルのパスを指定します。
    • デフォルトのパスを変更する場合は、Nginxの設定ファイル (nginx.confなど) のfastcgi_passディレクティブも合わせて変更する必要があります。

参考:🔗 php 公式 - php-fpm.conf と、プール設定ファイル

Nginxとの連携 🔗

PHP-FPM を Nginx と連携させることで、Nginx を Webサーバー として PHP の処理を PHP-FPM に任せることができます。

以下は PHP-FPM を Nginx と連携するための設定を Nginx の設定ファイル nginx.conf で記述する例です。

📝 nginx.conf の設定例

nginx.conf
server {
    listen 80;
    server_name example.com;
    root /var/www/html;

    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include fastcgi_params;  # FastCGIの基本設定を読み込む
        fastcgi_pass unix:/run/php-fpm/php-fpm.sock;  # PHP-FPMと接続
        fastcgi_index index.php;  # デフォルトのPHPスクリプト
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;  # 実行するPHPファイルを指定
    }
}

🗣️ 各ディレクティブの解説

  • try_files
    • 引数を前から順番にファイルがあるかをどうかを調べていき、なければ最後の引数の処理をします。(この場合404 エラーを返す)
    • $uri はアクセスされた URL のパス部分を表します。
  • include fastcgi_params
    • FastCGI の環境変数を設定するファイル (/etc/nginx/fastcgi_params) を読み込みます。
    • 次の fastcgi_param は、fastcgi_params に含まれていない変数を追加するために使用されます。
  • fastcgi_param
    • Nginx が PHP-FPM にリクエストを渡す際に、FastCGI の環境変数を設定するために使用されます。
  • fastcgi_pass
    • FastCGI サーバー(PHP-FPM)のアドレスを指定します。
    • ここでは、PHP-FPMの www プールの設定で指定したアドレス /run/php-fpm/php-fpm.sockを指定しています。

PHP の PATH_INFO について ✍️

PHP プログラムでは PATH_INFO という変数がよく利用されます。

PATH_INFO とは、PHP スクリプトのファイル名の後に追加情報を付与するための仕組みです。
例えば、以下の URL の extra/info の部分が PATH_INFO になります。

https://example.com/index.php/extra/info

しかし、nginx.conflocation ~ \.php$ では、このようなパスを処理できません。

PATH_INFO に対応する場合は、少し複雑な正規表現で設定を追加する必要があります。

📝 PATH_INFO を処理する設定

nginx.conf
server {
    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        if (!-e $document_root$fastcgi_script_name) {
            return 404;
        }fastcgi_param PATH_INFO $fastcgi_path_info;}
}

🗣️ 各ディレクティブの解説

  • location ~ [^/]\.php(/|$)
    • \.php の前の [^/] は、/dir/.php のようにドットで始まるファイルを除外するための表現です。
    • 末尾の (/|$) は、.php で終わるパスまたは / が続くパスのみを対象にします。
  • fastcgi_split_path_info
    • スクリプトファイル名と PATH_INFO を分割し、それぞれ $fastcgi_script_name$fastcgi_path_info に格納します。
    • 例: /dir/file.php/arg1$fastcgi_script_name = /dir/file.php, $fastcgi_path_info = /arg1
    • これらの変数を fastcgi_param ディレクティブで FastCGI に渡します。
  • if (!-e $document_root$fastcgi_script_name)
    • fastcgi_split_path_info で分割されたファイル名のファイルが存在しない場合に「404 (Not Found)」を返すように指定しています。

まとめ 🎯

Nginx と PHP-FPM の連携により、PHP アプリの高速処理が可能になる🚀
設定ファイル (nginx.conf) を適切に記述し、リクエストの処理をスムーズに🎛️

業務で PHP アプリケーションの設定をリファクタリングする中で学んだ内容をまとめました💻

もしご指摘やアドバイスがありましたら、コメントいただけますと幸いです📝
以上、えみり〜でした|ωΦ)ฅ

参考 ✨

Discussion