ローカル環境向けDocker Compose
PHP、データベース、キャッシュをローカルでまとめて実行します。
「ローカル環境向けDocker Compose」はCoddyKit上の無料PHP Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPHP Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 PHP Academyコースには全4レッスンが含まれています。
Composeによるローカルスタック
実際のPHPアプリはPHPだけでは動きません。データベース、キャッシュ、ときにはキューやメールキャッチャーも必要です。Docker Composeを使うと、これらを1つのファイルでサービスとして宣言し、共有ネットワークに接続して、名前で互いにアクセスできるようにします。
このレッスンでは、ボリューム、ヘルスチェック、依存関係の順序付けを含む、PHP-FPM + nginx + MySQL + Redisの完全なローカルスタックを構築します。
サービスの基本構成
Composeファイルでは、services:の下にサービスを列挙します。各サービスはDockerfileからbuildすることも、imageを取得することもできます。Composeは、すべてのサービスがキーで到達できるデフォルトネットワークを作成します。PHPアプリはMySQLにlocalhostではなくホストdbで接続します。
services:
app:
build:
context: .
target: dev # multi-stage dev target
volumes:
- ./:/app # live code mount
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.4
redis:
image: redis:7-alpineFPMの前段にnginxを置く
FPMはHTTPではなく、ポート9000でFastCGIを使用します。nginxがHTTPを終端し、.phpリクエストをapp:9000にプロキシします。nginxの設定では、Compose上の名前でPHPサービスを参照します。
# docker/nginx/default.conf
server {
listen 80;
root /app/public;
index index.php;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000; # service name from compose
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}Webサービスを接続する
nginxサービスは、SCRIPT_FILENAMEを解決するために同じコードと設定ファイルをマウントし、ポート80を公開し、appに依存します。両方が/appを共有するため、FastCGIの両側でパスが一致します。
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./:/app:ro
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app永続ボリューム
コンテナのファイルシステムは一時的なものです。名前付きボリュームを使うと、docker compose downの後もデータベースファイルを保持できます。バインドマウント(./:/app)を使うと、開発中にホスト上のコードをリアルタイムで同期できます。状態を持つデータには名前付きボリュームを、ソースにはバインドマウントを使ってください。
services:
db:
image: mysql:8.4
environment:
MYSQL_DATABASE: app
MYSQL_USER: app
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: rootsecret
volumes:
- dbdata:/var/lib/mysql
volumes:
dbdata: # survives `down`, removed only by `down -v`ヘルスチェックとdepends_on
depends_onだけでは、コンテナが起動するまでしか待機せず、MySQLが接続を受け付ける状態になるまで待機しません。healthcheckを追加し、condition: service_healthyを使うことで、DBの準備が実際に完了するまでアプリを待機させてください。
services:
db:
image: mysql:8.4
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-prootsecret"]
interval: 5s
timeout: 3s
retries: 10
app:
build: .
depends_on:
db:
condition: service_healthy # waits for healthcheck pass環境変数と.env
Composeは変数の置換用に、同じディレクトリにある.envを自動的に読み込みます。アプリの設定はenvironmentまたはenv_fileで渡します。コミットするComposeファイルにシークレットを含めず、代わりに変数を参照してください。
services:
app:
build: .
env_file:
- .env
environment:
DATABASE_URL: "mysql://app:secret@db:3306/app"
REDIS_URL: "redis://redis:6379"
# .env (gitignored) provides ${...} substitutions
# MYSQL_PASSWORD=secretPHPから接続する
ネットワーク内では、ホスト名がサービス名になります。PHPコードからはdbとredisに直接接続します。このスニペットは、設定レイヤーが行うようにDSNを解析し、Composeのサービス名が接続文字列にどのように組み込まれるかを示します。
<?php
$dsn = 'mysql://app:secret@db:3306/app';
$p = parse_url($dsn);
printf("driver: %s\n", $p['scheme']);
printf("host: %s\n", $p['host']); // 'db' resolves via compose DNS
printf("port: %d\n", $p['port']);
printf("db: %s\n", ltrim($p['path'], '/'));
$pdoDsn = sprintf('mysql:host=%s;port=%d;dbname=%s', $p['host'], $p['port'], ltrim($p['path'], '/'));
echo $pdoDsn . PHP_EOL;
?>ローカル開発用のXdebug
Xdebugの設定は、devビルドターゲットを通じてローカル環境でのみマウントしてください。client_hostをhost.docker.internalに設定すると、デバッガーがホスト上のIDEに接続できます。Xdebugはパフォーマンスを大幅に低下させるため、本番環境には決して含めないでください。
; docker/php/xdebug.ini (mounted only in dev)
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003単発コマンドを実行する
docker compose runは、マイグレーション、テスト、Composerの実行用に一時的なコンテナを起動します。execは、すでに実行中のサービス内でコマンドを実行します。使い捨てのコンテナをクリーンアップできるよう、タスクにはrun --rmを使ってください。
# Run migrations against the running db
docker compose exec app php bin/console doctrine:migrations:migrate
# One-off: install deps without a long-lived container
docker compose run --rm app composer install
# Tail logs of just the web service
docker compose logs -f webオーバーライドファイル
Composeはdocker-compose.ymlとdocker-compose.override.ymlを自動的にマージします。ベースファイルには本番を想定したデフォルト設定を保ち、開発専用のボリューム、ポート、Xdebugはオーバーライドに記述してください。これにより、CIはベースファイルを使い、開発者は追加設定をそのまま利用できます。
# docker-compose.override.yml (auto-merged, dev only)
services:
app:
volumes:
- ./docker/php/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini:ro
environment:
APP_ENV: dev
# CI runs: docker compose -f docker-compose.yml up (no override)確認
マイグレーションを実行する前に、単純なdepends_on: [db]だけでは不十分なのはなぜですか?
まとめ
Composeでローカルスタックを構築しました。nginxの背後にPHP-FPMを配置し(FastCGIでapp:9000に接続)、サービス名でMySQLとRedisにアクセスし、永続化には名前付きボリュームを使い、ヘルスチェックでdepends_onを制御し、環境変数による設定を行い、開発専用のオーバーライドでXdebugを有効にし、run/execで単発コマンドを実行しました。
覚えておくこと: サービス名はDNSホスト名として機能し、オーバーライドファイルによって開発用の追加設定をCIから分離でき、ヘルスチェックは単純な起動順序より信頼できます。
よくある質問
「ローカル環境向けDocker Compose」レッスンは無料ですか?
はい。「ローカル環境向けDocker Compose」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、PHP Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 PHP Academyコースには全4レッスンが含まれています。
「ローカル環境向けDocker Compose」で何を学びますか?
PHP、データベース、キャッシュをローカルでまとめて実行します。 ブラウザで直接実行するハンズオンコードでPHP Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
PHP Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPHP Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「ローカル環境向けDocker Compose」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPHP Academyレッスンでコードを書いて実行できますか?
はい。すべてのPHP Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- PHPアプリケーションのコンテナ化
- マルチステージビルドと最適化
- ローカル環境向けDocker Compose
- GitHub ActionsによるCI/CD