はじめに
Laravel Sail の環境構築では laravel.build を使う方法がよく紹介されています。しかしこの方法ではLaravelのバージョンを固定できません。本記事では Docker コンテナ内の Composer を使用して Laravel10 を確実にインストールする方法を解説します。
環境
- Windows 11
- WSL2 (Ubuntu)
- Docker Desktop(Windowsにインストール)
-
/etc/wsl.confでデフォルトユーザー設定済み
(WSL起動時にrootではなく通常ユーザーでログインする設定)
目次
- 1. 前提条件
- 2. プロジェクトの作成
- 3. .envの設定
- 4. Laravel Sailを起動
- 5. マイグレーション
- 6. Laravel Top画面表示
- 7. バージョン確認
- 8. Laravel Sailを停止
- 9. 通常の起動手順
- 10. トラブルシューティング
- 11. まとめ
- 12. Mailpitを追加する
- 補足:インストール途中で Composer が異常終了した場合
1. 前提条件
- Docker Desktopが起動していること
- WSLにcomposerは不要(Dockerコンテナ内で実行するため)
注意:
curl -s https://laravel.build/... | bashはLaravelのバージョン指定ができない。そのため実行時点のテンプレートに依存し、最新メジャーバージョン(2026/07/14時点ではLaravel 13)がインストールされる可能性がある。Laravel 10を確実に使用したい場合はcomposer create-projectでバージョン指定する。
※Laravel Sail自体にバージョン制限はなく、laravel.build経由のプロジェクト作成時に最新バージョンがインストールされる点に注意。
2. プロジェクトの作成
作業ディレクトリを作成して移動する。
mkdir -p ~/projects
cd ~/projects
2-1. Dockerコンテナ内のComposerでLaravel 10を作成する
Laravelプロジェクトの作成、Sailの導入、Sail構成の生成は、失敗箇所を切り分けられるように分けて実行する。
docker run --rm \
-u "$(id -u):$(id -g)" \
-e COMPOSER_HOME=/tmp/composer \
-v "$(pwd)":/opt \
-w /opt \
laravelsail/php82-composer:latest \
composer create-project laravel/laravel:^10.0 laravel10-project
正常に完了したら、作成されたプロジェクトへ移動する。
cd laravel10-project
2-2. Laravel Sailの導入状況を確認する
Laravelのプロジェクトテンプレートによっては、Sailが最初から開発用依存関係に含まれている場合がある。
grep '"laravel/sail"' composer.json
laravel/sailが表示されなかった場合だけ、次のコマンドでSailを追加する。
docker run --rm \
-u "$(id -u):$(id -g)" \
-e COMPOSER_HOME=/tmp/composer \
-v "$(pwd)":/opt \
-w /opt \
laravelsail/php82-composer:latest \
composer require laravel/sail --dev
2-3. MySQLを使用するSail構成を生成する
docker run --rm \
-u "$(id -u):$(id -g)" \
-e COMPOSER_HOME=/tmp/composer \
-v "$(pwd)":/opt \
-w /opt \
laravelsail/php82-composer:latest \
php artisan sail:install --with=mysql
成功すると、プロジェクト直下にdocker-compose.ymlまたはcompose.yamlが生成される。
ls -la
コマンドの説明
| オプション・引数 | 説明 |
|---|---|
--rm |
コマンド終了後に一時コンテナを削除する |
-u "$(id -u):$(id -g)" |
コンテナ内で生成されるファイルの所有者をWSL側のユーザーに合わせ、root所有になることを防ぐ |
-e COMPOSER_HOME=/tmp/composer |
Composerのホームディレクトリを書き込み可能な/tmp/composerへ設定する |
-v "$(pwd)":/opt |
WSL側の現在のディレクトリを、コンテナ内の/optへマウントする |
-w /opt |
コンテナ内の作業ディレクトリを/optに設定する |
laravelsail/php82-composer:latest |
PHP 8.2とComposerを含むLaravel SailのComposerイメージを使用する |
composer create-project |
Composerパッケージから新しいプロジェクトを作成する |
laravel/laravel:^10.0 |
Laravelアプリケーションスケルトンを10系に固定する |
laravel10-project |
作成するプロジェクトのディレクトリ名 |
composer require laravel/sail --dev |
Sailが含まれていない場合に、開発用依存関係として追加する |
php artisan sail:install --with=mysql |
MySQLを含むSailのCompose構成を生成する |
[!NOTE]
-u "$(id -u):$(id -g)"を指定しても、.envへWWWUSERやWWWGROUPが自動追加されるわけではない。このオプションは、今回使用する一時的なComposerコンテナが生成するファイルの所有者を、WSL側のユーザーへ合わせるための指定である。
WWWUSERとWWWGROUPはSailコンテナのビルドや実行時に使われる別の値であり、必要な場合は後述の設定で追加する。
[!IMPORTANT]
composer create-project、composer require、sail:installを&&で連結すると、途中で異常終了した場合に後続処理が実行されない。また、プロジェクトや
vendorディレクトリだけが途中まで作成され、どこまで成功したのか判断しにくくなることがある。本記事では、処理を分けて正常終了を確認してから次へ進む。
3. .envの設定
既存のLAMP環境とポートが重複しないように、Laravel Sail側のWeb・MySQL外部接続ポートを変更する。
phpMyAdminを後から追加する場合に備えて、phpMyAdmin用のポートもあわせて設定しておく。
cd ~/projects/laravel10-project
sed -i 's/^APP_PORT=.*/APP_PORT=81/' .env
sed -i 's/^FORWARD_DB_PORT=.*/FORWARD_DB_PORT=3307/' .env
sed -i 's/^PHPMYADMIN_PORT=.*/PHPMYADMIN_PORT=8082/' .env
※
sedは対象行が存在する場合のみ置換される。存在しない場合は、下記の追記コマンドを使用すること。
※ phpMyAdminサービスを追加する手順は別記事で扱っている。本記事では、追加済みのphpMyAdminコンテナのポートを8082に変更する前提で記載している。
.envにAPP_PORT、FORWARD_DB_PORT、PHPMYADMIN_PORTが存在しない場合は以下で追記する:echo 'APP_PORT=81' >> .env echo 'FORWARD_DB_PORT=3307' >> .env echo 'PHPMYADMIN_PORT=8082' >> .env
WWWUSER / WWWGROUP の追加
Laravel SailのDockerfileビルド時には WWWUSER / WWWGROUP という環境変数が参照される。これらが .env に存在しない場合、docker compose build --no-cache 実行時に警告が出て、ビルドが失敗することがある(詳細はトラブルシューティング参照)。
プロジェクト作成時の -u "$(id -u):$(id -g)" はファイル所有者対策であり、WWWUSER / WWWGROUP とは別の指定である。以下のコマンドで .env に追記する:
echo "WWWUSER=$(id -u)" >> .env
echo "WWWGROUP=$(id -g)" >> .env
id -u/id -gの結果は環境によって異なる。多くのWSL環境では1000になることが多いが、固定値として記述せず、必ずコマンドで取得すること。
確認:
grep -E "APP_PORT|FORWARD_DB_PORT|PHPMYADMIN_PORT|WWWUSER|WWWGROUP" .env
以下のように表示されればOK:
APP_PORT=81
FORWARD_DB_PORT=3307
PHPMYADMIN_PORT=8082
WWWUSER=1000
WWWGROUP=1000
ポート構成
| LAMP環境 | Laravel 10 Sail | |
|---|---|---|
| Web | :80 | :81 |
| phpMyAdmin | :8081 | :8082 |
| MySQL | ホスト公開なし | :3307 |
4. Laravel Sailを起動
./vendor/bin/sail up -d
起動確認:
./vendor/bin/sail ps
--with=mysql のみで構築した場合、以下のように表示されればOK:
0.0.0.0:81->80/tcp
0.0.0.0:3307->3306/tcp
- Laravel側は
http://localhost:81でアクセスする - MySQLはホスト側
3307からコンテナ側3306に転送される
phpMyAdminは
--with=mysqlだけでは起動しない。phpMyAdminサービスを追加している場合のみ、0.0.0.0:8082->80/tcpのような行が追加で表示される。
5. マイグレーション(初回のみ)
MySQLコンテナが起動してから実行する。
(./vendor/bin/sail ps でSTATUSが healthy またはUpになっていればOK)
./vendor/bin/sail artisan migrate
以下のように表示されればOK:
INFO Running migrations.
2014_10_12_000000_create_users_table ........... DONE
2014_10_12_100000_create_password_reset_tokens_table ... DONE
2019_08_19_000000_create_failed_jobs_table ..... DONE
2019_12_14_000001_create_personal_access_tokens_table .. DONE
6. Laravel Top画面表示
ブラウザで以下にアクセス:
http://localhost:81
Laravelのトップページが表示されれば成功。
7. バージョン確認
./vendor/bin/sail artisan --version
Laravel Framework 10.x.x
と表示されればOK。
PHPバージョン確認
Laravel本体のバージョンだけでなく、Sailコンテナ内のPHPバージョンも確認する。
./vendor/bin/sail php -v
PHP 8.2系になっていればOK。
PHP 8.2.x ...
注意:ここで確認しているのはWSL2ホスト側のPHPではなく、Laravel Sailコンテナ内のPHPである。ホスト側で
php -vを実行した場合は、Ubuntu側にインストールされているPHPのバージョンが表示されるため、Sailで実際に使われるバージョンとは異なる場合がある。Laravel Sailコンテナ内のPHPを確認する場合は、必ず./vendor/bin/sail php -vを使用すること。
意図しないバージョンになっている場合
もしPHP 8.5など、意図しないバージョンが表示された場合は、compose.yaml の laravel.test サービスで使用しているruntimeを確認する。
grep -n "runtimes\|image:" compose.yaml
build.context と image の両方がPHP 8.2を指しているか確認する。以下が正しい設定である:
build:
context: './vendor/laravel/sail/runtimes/8.2'
dockerfile: Dockerfile
image: 'sail-8.2/app'
以下のような不整合になっている場合は注意が必要である:
build:
context: './vendor/laravel/sail/runtimes/8.5'
dockerfile: Dockerfile
image: 'sail-8.2/app'
この状態では、image 名は sail-8.2/app でも、実際にはPHP 8.5のruntimeを元にビルドしている。実際に使われるPHP runtimeは build.context の指定で決まるため、runtimes/8.2 と sail-8.2/app の両方を揃える必要がある。
修正後は、既存コンテナとイメージを作り直す:
./vendor/bin/sail down
docker compose build --no-cache
./vendor/bin/sail up -d
./vendor/bin/sail php -v
PHP 8.2系になっていれば完了。
8. Laravel Sailを停止
./vendor/bin/sail down
停止・削除されるもの
- コンテナ
- ネットワーク
保持されるもの
- ボリューム(MySQLデータ)
次回 ./vendor/bin/sail up -d で再起動してもデータは残る。
9. 通常の起動手順(2回目以降)
cd ~/projects/laravel10-project
./vendor/bin/sail up -d
./vendor/bin/sail artisan migrate は初回のみ必要。
補足:Sailコマンドのエイリアス設定
毎回 ./vendor/bin/sail と入力するのが手間な場合は、エイリアスを設定することで sail コマンドとして実行できる。
echo "alias sail='./vendor/bin/sail'" >> ~/.bashrc
source ~/.bashrc
これにより、以下のように簡略化できる:
sail up -d
sail down
sail artisan migrate
注意:このエイリアスはLaravelプロジェクトのディレクトリ内でのみ有効。
10. トラブルシューティング
Connection refusedエラーが出る場合
SQLSTATE[HY000] [2002] Connection refused
MySQLコンテナがまだ起動中のため。しばらく待ってから再実行する。
./vendor/bin/sail ps # STATUSがhealthyまたはUpになるまで待つ
./vendor/bin/sail artisan migrate
Docker permission deniedが出る場合
Docker Desktopが起動しているか確認する。WSLからDockerが使用できない場合はDocker DesktopのWSL Integrationを有効にする。
Docker Desktop → Settings → Resources → WSL Integration
ポートが反映されない場合
.env にポート設定が追加されているか確認する:
grep -E "APP_PORT|FORWARD_DB_PORT|PHPMYADMIN_PORT" .env
表示されない場合は手動で追加してコンテナを再起動する:
echo 'APP_PORT=81' >> .env
echo 'FORWARD_DB_PORT=3307' >> .env
echo 'PHPMYADMIN_PORT=8082' >> .env
./vendor/bin/sail down
./vendor/bin/sail up -d
docker compose build --no-cache で WWWUSER / WWWGROUP の警告が出る場合
以下のような警告やエラーが出る場合がある:
WARN[0000] The "WWWUSER" variable is not set. Defaulting to a blank string.
WARN[0000] The "WWWGROUP" variable is not set. Defaulting to a blank string.
groupadd: invalid group ID 'sail'
原因:.env に WWWUSER / WWWGROUP が設定されていないため、SailのDockerfile内の $WWWGROUP が空のまま解釈され、ビルドが失敗する。
対処:.env に追記してから再ビルドする:
echo "WWWUSER=$(id -u)" >> .env
echo "WWWGROUP=$(id -g)" >> .env
grep -n "WWWUSER\|WWWGROUP" .env
docker compose build --no-cache
一時的に環境変数を渡して実行する方法もある:
WWWUSER=$(id -u) WWWGROUP=$(id -g) docker compose build --no-cache
ただし、この方法は一時的な対処であるため、.env への追記を推奨する。
PHP 8.2にしたいのにPHP 8.5でビルドされる場合
compose.yaml のruntimeを確認する:
grep -n "runtimes\|image:" compose.yaml
image: sail-8.2/app だけではPHP 8.2になるとは限らない。実際に使われるPHP runtimeは build.context の指定で決まる。build.context が runtimes/8.5 になっていないか確認すること。
PHP 8.2で統一する場合は以下に揃える:
build:
context: './vendor/laravel/sail/runtimes/8.2'
dockerfile: Dockerfile
image: 'sail-8.2/app'
修正後は再ビルドする:
./vendor/bin/sail down
docker compose build --no-cache
./vendor/bin/sail up -d
./vendor/bin/sail php -v
PHP 8.2系が表示されれば完了。
11. まとめ
Laravel Sail環境は curl -s https://laravel.build/... | bash で簡単に作成できるが、Laravelのバージョンを固定できない点には注意が必要である。特定のLaravelバージョンを使用する場合は composer create-project laravel/laravel:^10.0 をDockerコンテナ内で実行する方法が最も確実で再現性が高い。
また、環境構築時には以下の点を押さえておくと、つまずきを減らせる:
-
-u "$(id -u):$(id -g)"はファイル所有者対策であり、Sailビルド時のWWWUSER/WWWGROUPとは別の指定である -
WWWUSER/WWWGROUPはSailのDockerfileビルド時に参照される環境変数であり、.envへの手動追記が必要である - PHP 8.2で構築したい場合は、
compose.yamlのbuild.context(runtimes/8.2)とimage(sail-8.2/app)を揃えること - ポート設定は
./vendor/bin/sail psで確認し、0.0.0.0:81->80/tcpと0.0.0.0:3307->3306/tcpが表示されれば反映済みである - 既存LAMP環境と共存する場合はポートの衝突に注意すること
今回つまずいたポイント
今回つまずいた原因は、新規Laravelプロジェクト作成後に .env へ環境固有の設定を追加していなかったことです。
composer create-project や php artisan sail:install --with=mysql では、LaravelプロジェクトやSail構成は作成されますが、既存LAMP環境と共存するための APP_PORT / FORWARD_DB_PORT や、Sailビルド時に使用する WWWUSER / WWWGROUP は自動では設定されません。
そのため、プロジェクト作成後に .env へ以下を追加する必要があります。
echo 'APP_PORT=81' >> .env
echo 'FORWARD_DB_PORT=3307' >> .env
echo "WWWUSER=$(id -u)" >> .env
echo "WWWGROUP=$(id -g)" >> .env
phpMyAdminを後から追加する場合は、必要に応じて以下も追加します。
echo 'PHPMYADMIN_PORT=8082' >> .env
12. Mailpitを追加する
Mailpitは、ローカル開発環境から送信されたメールを外部へ実送信せずに受け取り、ブラウザで内容を確認するための開発用メールツールである。
このプロジェクトは作成時に sail:install --with=mysql を実行しているため、Mailpitがまだ compose.yaml に含まれていない場合は、Sailの追加サービス機能を使用して追加する。
12-1. Mailpitサービスを追加する
Laravel Sailを起動した状態で、プロジェクトディレクトリから以下を実行する。
cd ~/projects/laravel10-project
./vendor/bin/sail artisan sail:add
サービスの選択画面が表示されたら、mailpit を選択する。
追加後、compose.yaml にMailpitサービスが含まれていることを確認する。
grep -n "mailpit" compose.yaml
12-2. Mailpit用の環境変数を確認する
.env のメール設定を確認する。
grep -E "^MAIL_|^FORWARD_MAILPIT" .env
以下の設定になっていることを確認する。
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
設定が存在しない場合、または異なる場合は .env を編集する。
MAIL_HOST=mailpitとMAIL_PORT=1025は、LaravelコンテナからMailpitコンテナへ接続するための内部接続設定である。ブラウザで開くMailpit管理画面のポートとは別なので、管理画面のポートを変更してもMAIL_PORTは1025のままにする。
12-3. 既存環境とポートが重複する場合
Mailpitは標準で次のホスト側ポートを使用する。
- SMTP受信用:
1025 - 管理画面:
8025
既存環境と重複する場合は、.env に別のホスト側ポートを追加する。
echo 'FORWARD_MAILPIT_PORT=1026' >> .env
echo 'FORWARD_MAILPIT_DASHBOARD_PORT=8026' >> .env
この設定を使用する場合でも、Laravel側のメール送信先は次のままにする。
MAIL_HOST=mailpit
MAIL_PORT=1025
12-4. Sailを再起動する
./vendor/bin/sail down
./vendor/bin/sail up -d
起動状態を確認する。
./vendor/bin/sail ps
標準ポートを使用している場合は、Mailpitに次のポート割り当てが表示される。
0.0.0.0:1025->1025/tcp
0.0.0.0:8025->8025/tcp
ポートを変更した場合は、次のように表示される。
0.0.0.0:1026->1025/tcp
0.0.0.0:8026->8025/tcp
12-5. Mailpit管理画面を開く
標準ポートの場合:
http://localhost:8025
ポートを 8026 に変更した場合:
http://localhost:8026
Laravelアプリからメールを送信し、Mailpitの管理画面にメールが表示されれば追加完了である。
Mailpitはローカル開発用であり、本番環境のメール送信には使用しない。
補足:インストール途中で Composer が異常終了した場合
今回の検証では、composer create-project の終盤で次のエラーが発生しました。
Generating optimized autoload files
Segmentation fault (core dumped)
この状態では、Laravelプロジェクトのディレクトリやvendorディレクトリが作成されていても、インストール処理が最後まで完了していない場合があります。
今回確認できた未完了の状態は、次のとおりです。
-
vendor/autoload.phpが生成されていない -
php artisanを実行できない -
sail:installが実行されていない -
compose.yamlが生成されていない -
.envのAPP_KEYが空 - 初期マイグレーションが未実行
なお、今回のログから確定できたのは、Composer実行中のPHPプロセスがSegmentation faultで異常終了したことまでです。
Docker Desktop、WSL、メモリ、コンテナイメージなど、直接的な原因までは特定できていません。
1. vendor/autoload.phpを確認する
プロジェクトディレクトリへ移動して確認します。
cd laravel10-project
ls -l vendor/autoload.php
次のようなエラーになる場合は、Composerのオートローダー生成が完了していません。
ls: cannot access 'vendor/autoload.php': No such file or directory
2. Composerのインストール処理を再実行する
プロジェクト直下で、composer installを単独で実行します。
docker run --rm \
-u "$(id -u):$(id -g)" \
-e COMPOSER_HOME=/tmp/composer \
-v "$(pwd)":/opt \
-w /opt \
laravelsail/php82-composer:latest \
composer install
composer.lockが存在する場合は、記録済みの依存関係を使用してvendorディレクトリを再構築します。
正常終了後、もう一度確認します。
ls -l vendor/autoload.php
3. Laravelが起動できることを確認する
docker run --rm \
-u "$(id -u):$(id -g)" \
-e COMPOSER_HOME=/tmp/composer \
-v "$(pwd)":/opt \
-w /opt \
laravelsail/php82-composer:latest \
php artisan --version
Laravelのバージョンが表示されれば、artisanを実行できる状態です。
4. Sail構成を生成する
compose.yamlまたはdocker-compose.ymlが存在しない場合は、Sail構成を生成します。
docker run --rm \
-u "$(id -u):$(id -g)" \
-e COMPOSER_HOME=/tmp/composer \
-v "$(pwd)":/opt \
-w /opt \
laravelsail/php82-composer:latest \
php artisan sail:install --with=mysql
生成を確認します。
ls -la
5. Sailを起動する
./vendor/bin/sail up -d
6. APP_KEYを確認する
grep '^APP_KEY=' .env
APP_KEY=のまま空の場合は、次を実行します。
./vendor/bin/sail artisan key:generate
7. 初期マイグレーションを実行する
Laravelの初期設定によっては、セッションやキャッシュの保存先としてデータベースを使用します。
./vendor/bin/sail artisan migrate
マイグレーション未実行の状態では、次のようなエラーが発生する場合があります。
SQLSTATE[42S02]: Base table or view not found
Table 'laravel.sessions' doesn't exist
再構築時の注意
同じプロジェクト名で作り直す場合、古いMySQLボリュームが残っていると、以前のデータベースが再利用される可能性があります。
ボリュームを確認します。
docker volume ls
対象プロジェクトを完全に初期化する場合は、ディレクトリ削除前に次を実行します。
./vendor/bin/sail down -v
すでにプロジェクトディレクトリを削除した場合は、対象ボリューム名を確認して個別に削除します。
docker volume rm laravel10-project_sail-mysql
ほかのプロジェクトのボリュームを誤って削除しないように注意してください。
今回発生したComposerのSegmentation faultは、MySQLボリュームを使用する前の処理で発生しました。
そのため、古いMySQLボリュームがSegmentation faultの直接原因だったとは判断できません。
※2026/07/11更新:目次リンクの修正と、Laravel Sail環境へMailpitを追加する手順を追記しました。
※2026/07/14更新:Laravel 10のインストール手順を見直し、Composer実行時の注意点とトラブル対応を追記しました。