公開日 2026-03-21

Windows 11でPHP 8.3/8.4/8.5を使い分ける環境構築(WSL2 + mise + Docker Compose)

Windows 11のWSL2環境でPHP 8.3と8.4と8.5を安全に切り替えるためのローカル運用手順をまとめる。

目次

  1. 1. ゴールと結論
  2. 2. 全体構成と役割分担
  3. 3. 前提条件と事前チェック
  4. 4. WSL2 + Ubuntu 24.04 のセットアップ
  5. 5. mise導入とPHP複数バージョン構築
  6. 5-1. miseをインストールする
  7. 5-2. PHPビルド依存パッケージを入れる
  8. 5-3. PHP 8.3 / 8.4 / 8.5 をインストールする
  9. 5-4. Composerを確認する
  10. 6. プロジェクト単位のバージョン固定(.mise.toml)
  11. 7. Docker Composeでミドルウェアを用意する
  12. 8. 動作確認シナリオ
  13. 8-1. PHP切替の確認
  14. 8-2. PostgreSQLの確認
  15. 8-3. Redisの確認
  16. 8-4. Mailpitの確認
  17. 8-5. 失敗例と復旧(mise activate 未反映)
  18. 8-6. 失敗例と復旧(gdlib / locate)
  19. 9. 日常運用ルール(更新・保守)
  20. 10. よくある詰まりどころ
  21. mise で切り替わらない
  22. /mnt/c 配下で動作が重い
  23. mise install php@... が失敗する
  24. composer が見つからない
  25. docker compose up でポート競合
  26. WSLで docker compose が動かない
  27. WSLターミナルとPowerShellを混在させてしまう
  28. まとめ

WindowsでPHP開発を続けながら、プロジェクトごとにPHPバージョンを安全に切り替えたい方向けの手順です。
PHP開発経験はあるが、WSL2やmiseの運用はこれから固めたい方を対象にしています。 ローカル開発環境の構築に絞って解説し、本番サーバー構築、Kubernetes、Dev Containersの全面運用は扱いません。

おすすめの構成は次の3点です。

  • PHPバージョン管理: mise
  • DB/Redis/Mailテスト環境: Docker Compose
  • 作業場所: WSL2(~/projects 配下)

1. ゴールと結論

この記事で作る完成状態は次の3点です。

  • 1台のWindows PCで php@8.3 / php@8.4 / php@8.5 を切り替えられる
  • プロジェクトごとに .mise.toml でバージョン固定できる
  • PostgreSQL / Redis / Mailpit を docker compose up -d で起動できる

今回の運用ルールはシンプルです。

  • PHPは mise で使う
  • Dockerはミドルウェアだけに使う

この役割分担にすると、どのPHPで動かしているかを見失いにくくなります。

運用方針としては次を基準にすると進めやすいです。

  • 新規開発の主軸: PHP 8.5
  • 互換確認: PHP 8.4 / 8.3

2. 全体構成と役割分担

構成は次のとおりです。

Windows 11
└─ WSL2 (Ubuntu 24.04)
   ├─ mise
   │  ├─ php@8.3
   │  ├─ php@8.4
   │  └─ php@8.5
   └─ Docker Compose
      ├─ postgres
      ├─ redis
      └─ mailpit

役割を表にすると次のようになります。

コンポーネント役割どこで操作するか
misePHPバージョン管理(Composerは同じWSL環境で実行)WSLターミナル
docker composePostgreSQL/Redis/Mailpit起動WSLターミナル
VS Code Remote-WSL編集と実行の統一Windows側VS Code + WSL接続

本記事では標準DBをPostgreSQLにしています。

プロジェクトは /mnt/c/... ではなく ~/projects/... に置きます。
WSL内でLinuxコマンドを使う場合、~/projects 配下の方が体感速度と安定性が高くなります。

3. 前提条件と事前チェック

Docker Desktopがインストール済みであることを前提とします。未導入の場合はDocker Desktop公式手順で導入してください。

WSLで docker compose を使うには、Docker Desktopの Settings > Resources > WSL IntegrationUbuntu-24.04 を有効化しておきます。

エディタは任意ですが、VS Codeを使う場合は Remote-WSL 拡張を入れておくと作業を統一しやすくなります。

PowerShell(管理者)で確認します。

wsl --status
wsl --list --verbose
docker version

確認ポイント:

  • wsl --list --verbose の対象ディストリビューションが VERSION 2
  • Docker Desktopが起動していて docker version が通る
  • タスクマネージャー > パフォーマンス > CPU で「仮想化: 有効」になっている

WSLが未導入なら次章のコマンドから始めてください。 Ubuntu 24.04がすでに起動できる状態なら、第4章は読み飛ばして第5章へ進んでください。

4. WSL2 + Ubuntu 24.04 のセットアップ

PowerShell(管理者)で実行します。

# Windows 11では既定でWSL2ですが、念のため明示
wsl --set-default-version 2
wsl --install -d Ubuntu-24.04

インストール後はWindowsを再起動します。再起動後、Ubuntuを初回起動してユーザー作成を済ませます。
以降はUbuntu(WSL)ターミナルで作業します。

sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential curl git unzip
mkdir -p ~/projects
cd ~/projects

この時点で、今後の作業ディレクトリを ~/projects に統一しておきます。

5. mise導入とPHP複数バージョン構築

5-1. miseをインストールする

スクリプト内容を確認したい場合は、先に curl https://mise.run で中身を確認してから実行してください。

curl https://mise.run | sh

bashで実行します:

echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
source ~/.bashrc

確認:

mise --version
mise doctor

5-2. PHPビルド依存パッケージを入れる

Ubuntu 24.04では、先に次の依存パッケージを入れておきます。

sudo apt update
sudo apt install -y \
  plocate pkg-config build-essential autoconf bison re2c \
  libxml2-dev libssl-dev libsqlite3-dev libcurl4-openssl-dev \
  libonig-dev libzip-dev libreadline-dev libicu-dev libpq-dev \
  libjpeg-dev libpng-dev libfreetype6-dev libgd-dev
sudo updatedb

sudo updatedb は初回のみ数分かかる場合があります。完了してから次へ進みます。

5-3. PHP 8.3 / 8.4 / 8.5 をインストールする

初回インストールはソースビルドになるため、環境によっては数分から十数分かかります。
失敗した場合は詳細ログを出して原因を確認します。

mise install php@8.3
mise install php@8.4
mise install php@8.5

失敗時のみ、詳細ログ付きで再実行します。

mise install --verbose php@8.5

グローバル既定を設定:

mise use --global php@8.5
php --version
mise list php

5-4. Composerを確認する

まずは composer が使えるか確認します。

composer --version

composer: command not found の場合は、mise のシムを更新して再確認します。

mise reshim
composer --version

それでも見つからない場合は、Composer を手動導入します。

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
sudo mv composer.phar /usr/local/bin/composer
rm composer-setup.php
composer --version

6. プロジェクト単位のバージョン固定(.mise.toml)

3つのサンプルプロジェクトを作って切替を確認します。

mkdir -p ~/projects/php83-app ~/projects/php84-app ~/projects/php85-app

cd ~/projects/php83-app
mise use php@8.3
php --version

cd ~/projects/php84-app
mise use php@8.4
php --version

cd ~/projects/php85-app
mise use php@8.5
php --version

mise use を実行すると、各ディレクトリに .mise.toml が作られます。
例:

[tools]
php = "8.3"

.mise.toml はプロジェクトの再現性に関わるため、Gitを使っている場合はリポジトリに含めておくのがおすすめです。
(Gitの初期設定がまだなら、この手順は後回しで大丈夫です。)

例: ~/projects/php83-app をGit管理している場合

cd ~/projects/php83-app
git add .mise.toml
git commit -m "chore: pin php version with mise"

.mise.toml を置いたディレクトリの外で composer を実行すると、意図したPHPバージョンではなくグローバル設定で動作する場合があります。composer は必ず対象プロジェクト配下で実行してください。

7. Docker Composeでミドルウェアを用意する

ここではPostgreSQL/Redis/Mailpitを起動します。PHPコンテナは作りません。

mkdir -p ~/projects/php-infra
cd ~/projects/php-infra

~/projects/php-infra/compose.yml:

services:
  postgres:
    image: postgres:17-alpine
    container_name: php-dev-postgres
    environment:
      POSTGRES_DB: app
      POSTGRES_USER: app
      POSTGRES_PASSWORD: app
      TZ: Asia/Tokyo
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 10s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7.4-alpine # 執筆時点の例。最新タグはDocker Hubで確認
    container_name: php-dev-redis
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 10

  mailpit:
    image: axllent/mailpit:latest # 執筆時点の例。最新タグはDocker Hubで確認
    container_name: php-dev-mailpit
    ports:
      - "1025:1025"
      - "8025:8025"

volumes:
  postgres_data:
  redis_data:

~/projects/php-infra/.env.example:

DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=app
DB_USERNAME=app
DB_PASSWORD=app
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
MAIL_HOST=127.0.0.1
MAIL_PORT=1025

.env.example.env にコピーして使います。

cp .env.example .env

起動・停止:

cd ~/projects/php-infra
docker compose up -d
docker compose ps
docker compose down

データを含めて初期化する場合:

docker compose down -v

8. 動作確認シナリオ

8-1. PHP切替の確認

cd ~/projects/php83-app && php --version
cd ~/projects/php84-app && php --version
cd ~/projects/php85-app && php --version

8.3.x / 8.4.x / 8.5.x がそれぞれ表示されればOKです。

8-2. PostgreSQLの確認

cd ~/projects/php-infra
docker compose exec postgres psql -U app -d app -c "SELECT version();"

バージョン文字列が返れば接続成功です。

8-3. Redisの確認

docker compose exec redis redis-cli ping

PONG が返ればOKです。

8-4. Mailpitの確認

ブラウザで http://localhost:8025 を開き、UIが表示されればOKです。

Mailpit UI

8-5. 失敗例と復旧(mise activate 未反映)

症状:

  • mise use php@8.3 を実行したのに php --version が変わらない

確認:

mise doctor
which php
echo $PATH | tr ':' '\n' | grep mise

復旧:

source ~/.bashrc

8-6. 失敗例と復旧(gdlib / locate

症状:

  • Package requirements (gdlib >= 2.1.0) were not met
  • locate: command not found

対処:

sudo apt update
sudo apt install -y plocate libgd-dev pkg-config
sudo updatedb

その後、mise install php@8.x を再実行します。

9. 日常運用ルール(更新・保守)

運用では、更新方針を先に決めておくと事故が減ります。

  • パッチ更新(例: 8.5.x)は定期的に適用
  • マイナー更新(8.4 -> 8.5)は案件ごとに計画移行

更新コマンド例:

# mise本体
mise self-update

# 利用中ツールの更新確認
mise outdated

# PHPの再取得(指定系列の最新パッチを取得)
mise install php@8.5

# Dockerイメージ更新
cd ~/projects/php-infra
docker compose pull
docker compose up -d

切り分けは次の順で行うと早いです。

  1. php --versionmise current php
  2. mise doctor
  3. docker compose ps
  4. ポート競合(5432/6379/8025)確認

10. よくある詰まりどころ

mise で切り替わらない

  • 原因: mise activate がシェルに未設定
  • 対応: シェル設定追記 -> source ~/.bashrc -> mise doctor

/mnt/c 配下で動作が重い

  • 原因: WSL上のI/O特性
  • 対応: ~/projects 配下へ移動

mise install php@... が失敗する

  • 原因: ビルド依存不足
  • 対応: 5章の依存パッケージを追加し、mise install --verbose php@8.5 でログを確認して再実行

composer が見つからない

  • 原因: mise のシム未更新、またはComposer未導入
  • 対応: まず mise reshimcomposer --version で確認し、見つからなければ5章の手順でComposerを手動導入

docker compose up でポート競合

  • 原因: 既存プロセスが同じポートを使用
  • 対応: compose.yml のホスト側ポートを変更(例: 5433:5432

WSLで docker compose が動かない

  • 原因: Docker DesktopのWSL Integrationが無効
  • 対応: Settings > Resources > WSL IntegrationUbuntu-24.04 を有効化し、Docker Desktopを再起動

WSLターミナルとPowerShellを混在させてしまう

  • 原因: 実行コンテキスト混在
  • 対応: PHP/Composer/mise/docker compose の日常操作はWSLターミナルに統一

まとめ

WindowsでPHPを複数バージョン運用するなら、WSL2 + mise + Docker Compose は手順の再現性と運用のしやすさを両立しやすい構成です。
「PHPはmise、ミドルウェアはDocker」という役割分離を守ることで、どのPHPで動かしているかを見失いにくくなります。

この構成を土台にすれば、案件ごとに .mise.toml だけでPHPバージョンを安全に固定できます。

シリーズ 2/5

このシリーズ

PHP開発環境とVS Code

  1. 1. Windows 11で始めるPHPローカル開発環境(WSL2 + Docker + PostgreSQL)
  2. 2. Windows 11でPHP 8.3/8.4/8.5を使い分ける環境構築(WSL2 + mise + Docker Compose) 現在の記事
  3. 3. VS Codeで始めるPHP開発環境(推奨拡張 + settings.json最小構成)
  4. 4. VS CodeでPHPコード整形をそろえる(EditorConfig + PHP CS Fixer最小導入)
  5. 5. VS Code + Xdebugでステップ実行入門(WSL2 + Docker)