Windows 11で始めるPHPローカル開発環境 や WSL2 + Docker + PHP + PostgreSQLで最小CRUDを作る のような Docker 前提記事へ入る前に、どちらに何を書くかだけ先に整理するための補助記事です。
この 1 本では app 1 サービスの最小 PHP サンプルを使い、Dockerfile がイメージの中身、compose.yml がコンテナの起動方法を決める流れを切り分けます。Compose キーや Dockerfile 命令の全網羅、本番運用、Kubernetes は非対象です。
1. ゴールと非対象
到達する状態:
- PHP 拡張やベースイメージを変えたいときに
Dockerfileを見る - ポート公開、環境変数、マウント、起動コマンドを変えたいときに
compose.ymlを見る - 既存記事のサンプルを読んだとき、どのファイルを直すべきか当たりを付けられる
扱わない内容:
- Docker の歴史や内部実装の深掘り
- Compose キーや Dockerfile 命令の全網羅
- 本番向けのセキュリティ設定やマルチステージビルド
- Kubernetes や複数サービス構成の設計論
Docker 全体を 1 回で覚える記事ではありません。 役割分担だけを先に固め、後続の記事を読みやすくすることに絞ります。
2. まず結論: Dockerfile はイメージ、compose.yml は起動方法
先に結論を 1 文で置くと、Dockerfile は「イメージの中身を決めるファイル」、compose.yml は「そのイメージをどう起動するかを決めるファイル」です。
迷ったときの切り分けはシンプルです。
それがビルド時に固定されることなら Dockerfile、起動時に差し替えたいことなら compose.yml を見ます。
| やりたいこと | まず見るファイル | 理由 |
|---|---|---|
| PHP 拡張や OS パッケージを足したい | Dockerfile | イメージの中身を build 時に変えるため |
| ベースイメージを変えたい | Dockerfile | どの土台でコンテナを作るかを決めるため |
| 公開ポートを変えたい | compose.yml | ホストとコンテナのつなぎ方は起動時の設定だから |
| ソースコードをマウントしたい | compose.yml | ホスト側のパスを bind mount する設定だから |
| 環境変数を渡したい | compose.yml | 実行環境ごとに差し替えやすいから |
| 起動コマンドだけ変えたい | compose.yml | CMD を上書きして試せるから |
関係を図にすると次の並びです。
flowchart LR
A["app/index.php"] -->|"COPY (build time)"| C["image"]
B["Dockerfile"] -->|"docker build"| C
D["compose.yml"] -->|"ports / volumes / environment"| E["container"]
C --> E
A -->|"bind mount (run time)"| E
Dockerfile だけではコンテナは起動しません。
compose.yml だけでは、イメージの中身は作れないままです。
2 つを分けて読むと、既存構成の修正箇所が見えやすくなります。
3. 最小構成を先に見る
本文では compose.yml 表記で統一します。
古い記事や既存リポジトリでは docker-compose.yml を見かけますが、役割の見方は同じです。
最小構成は 3 ファイルだけです。
docker-compose-vs-dockerfile-demo/
├─ compose.yml
├─ docker/
│ └─ php/
│ └─ Dockerfile
└─ app/
└─ index.php
作業ディレクトリを作って開きます。
mkdir -p ~/projects/docker-compose-vs-dockerfile-demo/app
mkdir -p ~/projects/docker-compose-vs-dockerfile-demo/docker/php
cd ~/projects/docker-compose-vs-dockerfile-demo
code .
3-1. compose.yml を作成する
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
ports:
- "8080:80"
volumes:
- ./app:/var/www/html
environment:
APP_MESSAGE: "Hello from compose.yml"
3-2. docker/php/Dockerfile を作成する
FROM php:8.5-apache
WORKDIR /var/www/html
COPY app/ /var/www/html/
CMD ["apache2-foreground"]
3-3. app/index.php を作成する
<?php
declare(strict_types=1);
$message = getenv('APP_MESSAGE') ?: 'Hello from Dockerfile';
echo "<h1>{$message}</h1>";
echo '<p>PHP version: ' . PHP_VERSION . '</p>';
起動確認は最小限で十分です。
docker compose config
docker compose up -d --build
curl http://localhost:8080
Hello from compose.yml と PHP バージョンが表示されれば成功です。
このサンプルで押さえたい点は 2 つあります。
DockerfileのCOPYで、build 時点のapp/をイメージへ入れているcompose.ymlのvolumesで、起動時にはホスト側の./appをその場所へマウントしている
ローカル開発では volumes のほうが実行中コンテナの見え方を左右します。
そのため、ソースを直したいだけなら compose.yml 側の bind mount を見るのが近道です。
4. Dockerfile は何を決めるか
Dockerfile は、これから作るイメージの中身を上から順に定義します。
今回の最小例なら、読めば十分です。
FROM php:8.5-apache
WORKDIR /var/www/html
COPY app/ /var/www/html/
CMD ["apache2-foreground"]
各行の役割:
FROM php:8.5-apache- どのイメージを土台にするかを決めます。PHP の種類や OS 側の前提はここから始まります。
WORKDIR /var/www/html- 以後の作業場所をコンテナ内のどこに置くかの指定です。
docker compose exec app pwdで入ったときの基準点にもなります。
- 以後の作業場所をコンテナ内のどこに置くかの指定です。
COPY app/ /var/www/html/- build 時点のホストファイルをイメージへコピーする命令です。bind mount を使わない環境でも、イメージだけで最低限動く形を作れます。
CMD ["apache2-foreground"]- コンテナ起動時の既定コマンドです。毎回の起動で同じ既定値にしたいなら、ここへ書きます。
今回の最小例では RUN を省いています。
理由は、責務比較の主役が Dockerfile と compose.yml の切り分けだからです。
PHP 拡張や OS パッケージを入れたいなら、追加先は Dockerfile です。
たとえば今の Dockerfile に次を COPY の前へ足すと、PostgreSQL 用の拡張を build 時に組み込めます。
RUN apt-get update \
&& apt-get install -y --no-install-recommends libpq-dev \
&& docker-php-ext-install pdo_pgsql \
&& rm -rf /var/lib/apt/lists/*
ここでやっているのは、起動時の一時設定ではなくイメージの変更です。
だから compose.yml ではなく Dockerfile へ書きます。
5. compose.yml は何を決めるか
compose.yml は、作ったイメージをどう起動するかをまとめるファイルです。
単一サービスでも役割ははっきりしています。
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
ports:
- "8080:80"
volumes:
- ./app:/var/www/html
environment:
APP_MESSAGE: "Hello from compose.yml"
各項目の見方:
services- 何個のコンテナをどういう名前で扱うかを決めます。今回は
app1 つだけです。
- 何個のコンテナをどういう名前で扱うかを決めます。今回は
build- どのディレクトリを build context にして、どの
Dockerfileを使うかの指定です。ここは「Dockerfile を使う入口」であって、イメージの中身そのものを書く場所ではありません。
- どのディレクトリを build context にして、どの
ports- ホストの
8080をコンテナの80へつなぐ設定です。公開ポートを変えたいときはここを直します。
- ホストの
volumes- ホストの
./appをコンテナの/var/www/htmlへ bind mount する設定です。ローカルでソース変更をすぐ反映したいときに使います。
- ホストの
environment- 実行時に環境変数を渡します。今回の
APP_MESSAGEの受け取り元はここです。
- 実行時に環境変数を渡します。今回の
command も compose.yml 側の役割です。
これは Dockerfile の CMD を起動時だけ上書きするための設定で、環境ごとに起動方法を変えたい場面で使います。
既定値として全環境で持たせたいなら Dockerfile の CMD、特定の環境や一時的な上書きなら compose.yml の command と覚えておくと迷いにくくなります。
6. どちらに書くべきかを具体例で整理する
ここが実務で最も役立つ部分です。 「やりたいこと」と「その理由」を短く結びます。
| やりたいこと | 書く場所 | 理由 |
|---|---|---|
| PHP 拡張を入れたい | Dockerfile | build したイメージへ組み込む変更だから |
ベースイメージを php:8.5-apache から別のものへ変えたい | Dockerfile | どの土台でコンテナを作るかを固定するため |
| 作業ディレクトリを変えたい | Dockerfile | コンテナ内の既定の作業場所を変えるため |
localhost:8080 ではなく localhost:9000 で開きたい | compose.yml | ホスト側のポート公開は起動時設定だから |
| ホストのソースコードをそのまま反映したい | compose.yml | bind mount は実行中コンテナへの接続設定だから |
.env や環境ごとに値が違う環境変数を渡したい | compose.yml | 実行環境ごとに差し替えやすいから |
| 起動コマンドだけを一時的に変えたい | compose.yml の command | Dockerfile を rebuild しなくても CMD を上書きできるから |
| 全環境で共通の既定コマンドにしたい | Dockerfile の CMD | イメージの既定動作として持たせたいから |
迷ったら、次の 2 問です。
- その変更は build し直さないと反映されないか
- 環境ごとに差し替えたい設定か
1 つ目が yes なら Dockerfile、2 つ目が yes なら compose.yml を疑うと整理しやすくなります。
7. 既存記事を読むときの見方
このブログの Docker 前提記事を読むときも、順番は同じです。
- まず
compose.ymlを開く servicesの数、ports、volumes、environmentを見るbuildがあれば、その先のDockerfileを開くcommandがあればDockerfileのCMDを上書きしていないか確認する
この順で読むと、構成の全体像と修正場所が分かれます。
逆順で Dockerfile から入ると、サービス数や公開ポートを見落としやすい流れです。
次に読む候補:
- Windows 11で始めるPHPローカル開発環境(WSL2 + Docker + PostgreSQL)
- Windows 11でPHP 8.3/8.4/8.5を使い分ける環境構築(WSL2 + mise + Docker Compose)
- WSL2 + Docker + PHP + PostgreSQLで最小CRUDを作る
8. よくある勘違い
Dockerfile にポート公開を書くと思ってしまう
Dockerfile にも EXPOSE は書けますが、ホストのどのポートで受けるかまでは決まりません。
localhost:8080 のような公開設定は compose.yml の ports で決めます。
COPY したからローカル修正がすぐ反映されると思ってしまう
COPY は build 時点のファイルをイメージへ入れる命令です。
ローカル開発でファイル変更を即反映したいなら、見るべきなのは compose.yml の volumes です。
build があるから compose.yml がイメージの中身も決めているように見える
build は「この Dockerfile を使って build する」という入口にすぎません。
何をインストールし、何をコピーし、どの CMD を既定にするかは Dockerfile 側で決まります。
起動コマンドを変えるたびに Dockerfile を直してしまう
全環境で同じ既定値に変えたいなら CMD を直す価値があります。
一方で、開発環境だけ少し変えたいなら compose.yml の command で十分です。
9. まとめ
Dockerfile はイメージの中身、compose.yml はコンテナの起動方法です。
この 2 つを分けて読むだけで、既存の Docker 構成は追いやすくなります。
次に既存記事を見るときは、まず compose.yml の services と ports を見てから、build 先の Dockerfile を開いてください。
その順番が定着すると、「PHP 拡張を足したいのに compose.yml を触っていた」「ポートを変えたいのに Dockerfile を見ていた」という迷いが減ります。