PHP-FPMをDockerで構築する場合は、PHP-FPMとWebサーバーを別々のコンテナに分ける構成が基本です。
代表的なのは、NginxとPHP-FPMを組み合わせる構成です。
ブラウザ
↓
Nginxコンテナ
↓ FastCGI
PHP-FPMコンテナ
↓
PHPアプリケーション
NginxがHTTPリクエストを受け取り、PHPファイルの処理が必要な場合はFastCGI経由でPHP-FPMへ処理を渡します。
PHP-FPMは受け取ったPHPファイルを実行し、その結果をNginxへ返します。
Dockerを利用すれば、NginxやPHP-FPMをそれぞれ独立したコンテナとして管理できるため、開発環境を統一しやすくなります。
PHP-FPMとは
PHP-FPMは「PHP FastCGI Process Manager」の略称です。
PHPをFastCGI方式で動作させるための仕組みで、PHPを実行する複数のプロセスを効率的に管理します。
PHP-FPMはWebサーバーではない
PHP-FPM自体は、NginxやApacheのような一般的なWebサーバーではありません。
通常はNginxなどのWebサーバーと組み合わせて使用します。
処理の流れは次のようになります。
ユーザー
↓
Nginx
↓
PHP-FPM
↓
PHPアプリケーション
↓
PHP-FPM
↓
Nginx
↓
ユーザー
HTMLやCSS、JavaScript、画像などの静的ファイルはNginxが配信し、PHPの実行が必要な場合だけPHP-FPMへ処理を渡す構成が一般的です。
DockerでPHP-FPM環境を構築する
ここでは、NginxとPHP-FPMをDocker Composeで構築する方法を紹介します。
ディレクトリ構成は次のようにします。
php-fpm-docker/
├── compose.yaml
├── docker/
│ ├── php/
│ │ └── Dockerfile
│ └── nginx/
│ └── default.conf
└── src/
└── index.php
Docker Composeを利用すると、PHP-FPMやNginxなど複数のコンテナを1つの設定ファイルでまとめて管理できます。
PHP-FPM用のDockerfileを作成する
まず、docker/php/Dockerfileを作成します。
FROM php:8.4-fpm
WORKDIR /var/www/html
COPY ./src /var/www/html
PHP公式のFPMイメージを使用する
PHPの公式DockerイメージにはFPM版が用意されているため、PHP-FPMを一からインストールする必要はありません。
例えば、
FROM php:8.4-fpm
と指定すれば、PHP 8.4とPHP-FPMを含んだイメージを利用できます。
PHPのバージョンについては、実際のプロジェクト要件やサポート期間に合わせて選択することが重要です。
COPYのパスに注意する
今回のDocker Composeでは、プロジェクトルートをビルドコンテキストにします。
そのため、Dockerfileでは、
COPY ./src /var/www/html
と指定します。
COPYのコピー元はDockerfileが置かれている場所ではなく、Dockerのビルドコンテキストを基準に指定します。
Nginxの設定ファイルを作成する
次に、docker/nginx/default.confを作成します。
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
fastcgi_passでPHP-FPMへ処理を渡す
特に重要なのが次の部分です。
fastcgi_pass php:9000;
ここでNginxからPHP-FPMコンテナへPHPの処理を渡しています。
phpはDocker Composeで定義するサービス名です。
services:
php:
同じDocker Composeネットワーク内では、コンテナ同士をサービス名で参照できます。
そのため、NginxコンテナからPHP-FPMへ接続するときは、
fastcgi_pass localhost:9000;
ではなく、
fastcgi_pass php:9000;
と指定します。
Nginxコンテナ内でlocalhostを指定すると、Nginxコンテナ自身を指してしまうためです。
try_filesはフロントコントローラー型の構成で使われる
次の設定は、Laravelなどのフレームワークでもよく利用されます。
try_files $uri $uri/ /index.php?$query_string;
存在するファイルやディレクトリが見つからなかった場合に、リクエストをindex.phpへ渡す設定です。
単純に複数のPHPファイルを直接配置するだけの構成では、必ずしも必要ではありません。
compose.yamlを作成する
続いて、プロジェクトルートにcompose.yamlを作成します。
services:
php:
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./src:/var/www/html
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
この設定では、
php
nginx
という2つのサービスを起動します。
PHP-FPMコンテナの設定
PHP-FPM側は次の設定です。
php:
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./src:/var/www/html
buildでDockerfileからイメージを作成する
build:
context: .
dockerfile: ./docker/php/Dockerfile
では、プロジェクトルートをビルドコンテキストとして、指定したDockerfileからPHP-FPM用のイメージを作成します。
volumesでPHPファイルを共有する
volumes:
- ./src:/var/www/html
では、ホスト側のsrcディレクトリと、PHP-FPMコンテナ側の/var/www/htmlを共有します。
開発環境では、ローカル側でPHPファイルを編集するとコンテナ側にも反映されるため便利です。
Nginxコンテナの設定
Nginx側は次の設定です。
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
ポート8080からアクセスする
次の設定では、
ports:
- "8080:80"
ホスト側の8080番ポートと、Nginxコンテナ側の80番ポートを接続しています。
そのため、ブラウザから、
http://localhost:8080
へアクセスできます。
Nginx側にもsrcをマウントする
Nginx側にも、
- ./src:/var/www/html
を設定しています。
Nginxは静的ファイルを配信したり、try_filesでファイルの存在を確認したりするため、Nginx側からもアプリケーションファイルを参照できる必要があります。
index.phpを作成する
src/index.phpを作成します。
<?php
phpinfo();
これでPHPの動作確認ができます。
phpinfo()はPHPの設定情報やサーバー情報を詳しく表示するため、本番環境で公開し続けるのは避けましょう。
動作確認後は削除することをおすすめします。
Dockerコンテナを起動する
プロジェクトルートで次のコマンドを実行します。
docker compose up -d --build
--buildを付けることで、必要に応じてDockerイメージをビルドしてからコンテナを起動できます。
起動後、ブラウザから次のURLへアクセスします。
http://localhost:8080
PHPの情報画面が表示されれば、
Nginx
↓
PHP-FPM
↓
PHP
という連携が正常に動作しています。
Dockerコンテナの状態を確認する
起動中のコンテナを確認するには、次のコマンドを使用します。
docker compose ps
正常に起動していれば、PHPとNginxのサービスがUpなどの状態で表示されます。
ログを確認する
すべてのサービスのログを確認する場合は、
docker compose logs
リアルタイムで確認する場合は、
docker compose logs -f
を使用します。
PHP-FPMだけを確認したい場合は、
docker compose logs -f php
Nginxだけを確認する場合は、
docker compose logs -f nginx
と指定できます。
PHP-FPMコンテナ内でコマンドを実行する
PHP-FPMコンテナ内でコマンドを実行したい場合は、
docker compose exec php bash
を使用します。
PHPのバージョンを確認する場合は、
php -v
インストール済みのPHP拡張機能を確認する場合は、
php -m
PHP-FPMの設定を確認する場合は、
php-fpm -tt
などを利用できます。
MySQLを追加する場合
PHPアプリケーションでは、MySQLなどのデータベースを利用するケースも多くあります。
MySQLを追加すると、次のような構成になります。
ブラウザ
↓
Nginx
↓
PHP-FPM
↓
MySQL
Composeファイルは、例えば次のようにできます。
services:
php:
build:
context: .
dockerfile: ./docker/php/Dockerfile
volumes:
- ./src:/var/www/html
depends_on:
- db
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: sample
MYSQL_USER: sample
MYSQL_PASSWORD: password
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
MySQLデータはボリュームへ保存する
次の設定では、
volumes:
- mysql_data:/var/lib/mysql
MySQLのデータをDockerの名前付きボリュームへ保存しています。
コンテナを作り直した場合でも、ボリュームを削除しない限りデータを保持しやすくなります。
ただし、
docker compose down -v
のようにボリュームも削除すると、保存されているデータも失われる可能性があるため注意が必要です。
PHPからMySQLへ接続する
PHPからMySQLへPDOで接続する場合は、pdo_mysql拡張機能が必要です。
Dockerfileを次のように変更します。
FROM php:8.4-fpm
RUN docker-php-ext-install pdo_mysql
WORKDIR /var/www/html
COPY ./src /var/www/html
変更後は再ビルドします。
docker compose up -d --build
MySQLのホスト名はdbを指定する
Docker Compose環境では、PHPコンテナからMySQLへ接続するときにlocalhostを指定しません。
今回のサービス名は、
db:
なので、ホスト名にはdbを指定します。
例えばPDOでは次のようになります。
<?php
$pdo = new PDO(
'mysql:host=db;dbname=sample;charset=utf8mb4',
'sample',
'password'
);
PHPコンテナ内でlocalhostを指定すると、PHPコンテナ自身を指すため、MySQLコンテナへ接続できません。
depends_onの注意点
Docker Composeでは、
depends_on:
- db
と指定すると、依存するサービスの起動順序を制御できます。
ただし、depends_onを指定しただけでは、MySQLが実際に接続可能な状態になるまで待ってくれるわけではありません。
そのため、アプリケーション起動直後にMySQLへ接続すると、タイミングによっては接続エラーになる場合があります。
healthcheckを利用する方法もある
より確実にサービスの準備状態を確認する場合は、healthcheckを設定し、service_healthyを利用する方法があります。
例えば次のように構成します。
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: sample
MYSQL_USER: sample
MYSQL_PASSWORD: password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
PHP側では、
depends_on:
db:
condition: service_healthy
のように設定できます。
パスワードをComposeファイルへ直接書く場合の注意点
開発環境のサンプルでは、
MYSQL_ROOT_PASSWORD: root
MYSQL_PASSWORD: password
のように簡単なパスワードを直接記述することがあります。
ただし、このような書き方はローカル開発用の簡易例として考えたほうがよいでしょう。
本番環境では、データベースのパスワードやAPIキーなどの機密情報をソースコードやComposeファイルへ直接記述しないことが重要です。
環境変数やSecretsなど、用途に適した機密情報管理の仕組みを利用します。
PHP-FPMの設定を変更する
PHP-FPMでは、php-fpm.confやPool設定ファイルを使ってプロセス数などを調整できます。
例えば次のような設定があります。
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_childrenは同時処理数に関係する
pm.max_childrenは、PHP-FPMが同時に処理できる子プロセス数に関係する重要な設定です。
値を大きくすれば単純に性能が上がるわけではありません。
PHPプロセスが使用するメモリ量やサーバー全体のメモリ容量、アクセス数などを考慮して調整する必要があります。
小規模なローカル開発環境であれば、まずはデフォルト設定から始めてもよいでしょう。
開発環境と本番環境で構成を分ける
開発環境では、Bind Mountを使う構成が便利です。
ローカルファイル
↓
Bind Mount
↓
コンテナ
ファイルを編集するとすぐコンテナへ反映されるため、開発効率が高くなります。
一方、本番環境ではアプリケーションコードをDockerイメージへ組み込む構成も一般的です。
ソースコード
↓
Dockerイメージ
↓
コンテナ
例えば次のようにします。
FROM php:8.4-fpm
RUN docker-php-ext-install pdo_mysql
WORKDIR /var/www/html
COPY ./src /var/www/html
本番環境では、開発用のBind Mountをそのまま使用するのではなく、デプロイ方法や運用方針に合わせて構成を分けることが重要です。
.dockerignoreも設定する
Dockerイメージをビルドするときは、.dockerignoreを設定して不要なファイルをビルドコンテキストから除外すると効率的です。
例えば次のように設定できます。
.git
.env
node_modules
プロジェクト構成によってはvendorなども対象になりますが、Composerの依存関係をどの段階でインストールするかによって設定は変わります。
不要なファイルをビルドコンテキストへ含めないことで、ビルド時間やイメージ管理を改善しやすくなります。
PHP-FPMをDockerで構築するメリット
DockerでPHP-FPM環境を構築する大きなメリットは、開発環境を設定ファイルとして管理できることです。
例えば、
FROM php:8.4-fpm
と記述しておけば、使用するPHPのバージョンを明確にできます。
開発者ごとにPHPのバージョンや設定が異なる問題も減らしやすくなります。
NginxやMySQLを分離して管理できる
Dockerでは、
Nginx
PHP-FPM
MySQL
Redis
などを別々のコンテナとして管理できます。
役割ごとにコンテナを分離できるため、構成を理解しやすく、必要なサービスだけを変更しやすい点もメリットです。
Docker Composeを利用すれば、それらのサービスを1つのcompose.yamlでまとめて管理できます。
PHP-FPMをDockerで構築するときのポイント
PHP-FPMをDockerで構築する場合は、まずNginxとPHP-FPMの2コンテナ構成から始めると理解しやすいでしょう。
基本的な構成は次の通りです。
ブラウザ
↓
Nginxコンテナ
↓
PHP-FPMコンテナ
↓
必要に応じてMySQLコンテナ
PHP-FPMはPHPを実行するFastCGIプロセスマネージャーであり、一般的にはNginxなどのWebサーバーと組み合わせて利用します。
DockerではPHP公式のFPMイメージを利用できるため、
FROM php:8.4-fpm
のように指定するだけで、PHP-FPM環境の土台を簡単に用意できます。
さらにDocker Composeを使えば、Nginx、PHP-FPM、MySQLなどをまとめて管理できます。
開発環境ではBind Mountを利用し、本番環境ではアプリケーションをDockerイメージへ組み込むなど、目的に応じて構成を使い分けることも重要です。
まずはNginxとPHP-FPMの最小構成を構築し、必要に応じてMySQLやRedisなどのサービスを追加していくと、DockerによるPHP開発環境を理解しやすくなります。
以上、PHP-FPMをDockerで構築する方法についてでした。
最後までお読みいただき、ありがとうございました。










