(docker for Windows用)(初心者向け説明)Laravel開発環境の構築方法

## ■1 概要（原理やファイルシステムについて）
### LinuxやMacで構築したdocker環境をWindowsで実行すると劇遅になる
理由は下記に示しますが、LinuxやMacで構築したdocker環境を
Windows上にそのまま持ってくると、例えばLaravelで
0.5秒で表示できるページが5～15秒かかるなどの「劇遅」になる事が多々あります
この現象を見て「docker for Windos遅すぎて使えねぇ？」って勘違いする人も出そうです
### docker desktop for Windowsでの話
本説明は「docker desktop for Windows」を使ったWindows環境で
Linuxのdockerを使う時の話になります
Linux上やMac上でのdockerは前提のファイルシステムが異なるので違う話になります
### そもそもdockerのファイルシステムはどうなっているか？
他の人にdockerの環境構築をしてもらって使っている人は多いと思います
でも「dockerの環境がどうなっているか？」「dockerのファイルシステムがどうなっているか？」
を正確に理解できている人は意外と少ないのではないかと思います

WindowsとLinuxのファイルシステムは全く違っていて基本的に互換性がありません
この二つを無理やり共存させて相互アクセスさせている関係で様々な不都合があり
これらを解消する使い方が必要になります
### dockerコンテナ上のLinuxファイルは本来的にはWindowsからは見えない
後述する「WindowsファイルとLinuxファイルの共存設定」を使う事が多いので
知らない人が多いのではないかと思いますが、
「何も考えずにdocker-compose.ymlやDockerfileで構築したシステム」では
docker内のLinuxファイルにWindowsからアクセスする事ができません

（※）mysqlやpostgreSQLなどのDBの「ファイル」にWindowsから直接アクセスできない
事などが一例になるかと思います。本来はphpなどのソースファイルも同じです
### Windowsで編集したいフォルダ/ファイルだけWindowsからアクセスできる様に設定する
dockerのlinuxファイルシステムにWindowsからアクセスしたい場合には2種類の方法があります
#### wsl2のubuntu環境のフォルダをdockerで共有設定する
docker for Windowsはwsl2ベースでインストールする事が多いです
なのでwsl2のubuntu環境がインストールされている事が前提になります
なので
\\wsl.localhost\Ubuntu\home\（自分のユーザー名）
フォルダ以下にphpなどのソースファイルを置いて、
それをdocker-compose.ymlのvolumes設定で共有設定する事で
LinuxからもWindowsからもdockerからもアクセスできる環境が作れます
（wsl2のファイルシステムはdockerと違ってWindowsからもアクセスできるため）

メリット:Linuxファイルシステムなので速度が圧倒的に早い
デメリット:Windowsからのアクセスが不可能ではないが色々と面倒

（※）Laravel標準のLaravel sailなどはこの方式を使っています
（※）本説明ではこの方法は使いません
#### Windowsのフォルダをdockerで共有設定する
Windowsのフォルダをdocker-compose.ymlのvolumes設定で
共有設定する事で、Windowsからもdockerからもアクセスできる環境が作れます

メリット:Windowsからのアクセスが超簡単
デメリット:docker(Linux)からのアクセス速度が劇遅なので使い物にならない
（※）具体的にはLaravel1ページの表示で（本来は0.5秒とかの処理が）5秒～15秒くらいかかるイメージです
### 劇遅な理由は何なのか？
Windowsのフォルダを共有設定すると劇遅になる理由は、
例えばLaravelでは
/var/www/html/vendor
の様な「システムが頻繁に使う大量の小さなファイル」が
劇遅のWindowsファイルシステムにある事です
なので、「遅くなる原因のフォルダだけLinuxのファイルシステムを使えば解消できる」
が解決策になります
（本説明はこの方針での設定方法になります）
### dockerコンテナ上のファイルを消さない方法
上記の話とは関連もしつつ違う話にもなるのですが
「何も考えずに作ったdockerコンテナ上のファイルはdockerを終了すると全部消える」
という特性があります

具体的に言うと
docker-compose up -d
で開始したdocker環境を
docker-compose stop
で「消さずに中断している間」は内部のファイルも消えないのですが
docker-compose down
でコンテナを一度消してしまうと、中で変更したファイルも全部消えてしまいます
開発中のソースファイルやDBの中身が消えてしまうと困りますよね？

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/5ce59482-0c86-9f53-038a-a8af879024dc.png)

なので、docker-compose.ymlの中のvolumesというコマンドで
名前を付けた「永続的な仮想ディスク」を作成してこれをマウントする事で
docker-compose downしてもlinuxファイルが消えない様にする事ができます
```
volumes:
  vendor-store:
  db-store:
```
### （改めて）Windows版のwsl2の特性について
Windowsのwsl2を使ったLinux環境は基本的に高速なのですが
ファイルシステムに強いクセがあります

- Windows上のファイルはWindowsでアクセスすると速いがLinuxからアクセスすると劇遅
- Linux上のファイルはLinuxでアクセスすると速いがWindowsからアクセスすると劇遅

Laravel標準のLaravel sailなどではこの特性を解消する為に
「プロジェクトのファイルは全てWindows/Linux双方からアクセスできるubuntu側に格納する」
という手法を取っているのですが、これだと速いは速いのですが
ファイルシステムがWindowsからアクセスしづらいので
これはこれで使いにくいです

（※）Visual Studio CodeやSourceTreeなどで
「ubuntuのLinuxファイルシステムにアクセスできる機能」はあるにはあるのですが
やはり使いにくい面が多々あります

逆に「プロジェクトのファイルを全てWindows側に格納する」
という事をするとソースファイルの管理は楽になるのですが
（LaravelのシステムはLinux側で動いているので）
Laravelの動作が劇遅になります
具体的には1ページの表示で（本来は0.5秒とかの処理が）5秒～15秒くらいかかるイメージです

なので「システムファイルはLinux側に置きつつ」「ソースファイルをWindows側に置く」という構成で構築します
（実行速度と扱いやすさのバランスを取った構成になります）
### volumesの設定
LaravelやCakePHPなど「使っているフレームワークによっても違う」のですが
Laravelの場合は
/var/www/html/vendor
フォルダの大量アクセスが遅くなる原因なので
「ここだけLinuxのファイルとして扱う」
「それ以外はWindowsのファイルとして扱う」
事にします

具体的にはdocker-compose.yml設定中のvolumes:という設定を使います
linuxファイルのvolumesにはmysqlのdbファイル格納場所も設定します
（volumesで保存しておかないとコンテナをdownする度にmysqlの内容が消えるので）
```
volumes:
  vendor-store:
  db-store:

services:
  apache:
    volumes:
      - ./html:/var/www/html
      - vendor-store:/var/www/html/vendor

  mysql_db:
    volumes:
      - db-store:/var/lib/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
```
### volumesとは何か？
```
volumes:
  vendor-store:
  db-store:
```
の3つのvolumesとは「仮想ディスク」のファイルになります

Windowsのバージョンやdockerのバージョンによって保存場所が変わりますが
\\wsl.localhost\docker-desktop\tmp\docker-desktop-root\var\lib\docker\volumes
または
\\wsl.localhost\docker-desktop-data\data\docker\volumes
というフォルダの下に
(プロジェクト名)_（volumes名）
形式のファイルが作られ、その中に指定したフォルダ以下のファイルが全て入っています
VMwareやVirtualBoxやHyper-Vの仮想ディスクと同じイメージです

（※）仮想ディスクの中身はWindowsから見ることができます
dockerコンテナ内のlinuxファイルが見れないのとは少し状況が変わります

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/ca4590f7-7d0a-14ea-2b9c-8ff653fd72e5.png)
### Lavavelの問題
（※）あっちもこっちも問題点が多すぎです
実は、この構成にするに際して「Lavavelの問題」「Laravelの大問題」があります
今回
/var/www/html
をWindowsの./htmlフォルダにマウントして
/var/www/htmlフォルダ以下の
/var/www/html/vendor
/var/www/html/storage/framwwork
の2つのサブフォルダだけdockerのvolumesとしてlinuxファイルとしたいのですが
Laravelのプロジェクトを作成するコマンド
docker-compose build –no-cache –force-rm
では
「/var/www/htmlフォルダ以下が空でなければ実行できない」
という致命的な問題があってdocker-compose buildコマンドが実行できません
なので「他のフォルダでdocker-compose buildで作成したプロジェクトをコピーする流れ」
で実行していこうと思います（非常に面倒な話です）
## ■2（プロジェクト作成者向け）新規のLaravel開発環境を構築する
ここではLaravel用の新規開発ファイルを用意しました
本ページからダウンロードしたdocker_laravel.zipファイルを解凍すると下記の様なファイルが展開されます

（※）apache/Laravel/mysql/phpmyadminという構成になります

（※）フォルダ名の「docker_laravel」は適当なフォルダ名に変えてください
.env.sampleファイルを.envとコピーして.envファイルの内容を編集する事になります

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/d999cdf2-75db-d1e5-9f63-6dc1fb7db294.png)

### 添付ファイルのダウンロード（dockerプロジェクトファイル一式）
添付ファイルはここからダウンロードしてください

（※）私の個人blogからのリンクになります
（blogのURL）

https://nisimura.org/docker_for_windows_laravel_project/

（zipファイルの直リンク）

https://nisimura.org/wp-content/uploads/2025/03/docker_laravel.zip

### htmlフォルダの確認と.htaccessファイルのコピー
gitの関係でプロジェクト直下にhtmlフォルダが作成されていないかもしれません
その場合は手動でhtmlフォルダを作成し、プロジェクトルートフォルダにある
.htaccessファイルをhtmlフォルダ内にコピーしておいてください

### .envファイルの編集
.envファイルの内容は下記の様になっています
```
PROJECT_NAME=laravel_project1
WEB_NAME=laravel
WEB_PORT=9000
DB_NAME=mysql
DB_PORT=9002
DB_DATABASE_NAME=mysql_db
DB_USER=root
DB_PASS=root
PHPMYADMIN_NAME=phpmyadmin
PHPMYADMIN_PORT=9001
```
各項目はdockerのコンテナ一覧に表示されるプロジェクト名／コンテナ名に該当し
PROJECT_NAME・・・プロジェクト名
WEB_NAME・・・Apache/PHPコンテナ名
PHPMYADMIN_NAME・・・phpmyadminコンテナ名
DB_NAME・・・mysqlコンテナ名
となります

複数のdockerコンテナを同時に起動する可能性がある場合を考慮して
プロジェクト名や各コンテナ名は他のdockerプロジェクトと
重複しない様にした方がいいかもしれません
（番号などで分けるのが分かりやすいと思います）

（※）重複した際の番号は自動で付くかもしれないので番号なしでもいいかもしれません（確認不足）

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/cb2b2108-f421-884a-7a0d-83cabe7efd17.png)

### gitの登録
今回の形式では「docker環境用」と「Laravelソースファイル用」で
2つのgitを登録する事を想定しています
プロジェクトルートに.gitignoreファイルは用意してあるので
プロジェクトルートフォルダをdocker用としてgit登録してください
### docker環境の構築
1.コマンドプロンプトなどでdocker-compose.ymlのあるフォルダに移動し
下記のコマンドを実行します
（※）環境構築に数分程度時間がかかります
```
docker-compose build --no-cache --force-rm
```
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/17f95683-f5ee-544e-ec99-b5c414fe6e0a.png)
2.コマンドプロンプトで下記のコマンドを実行してdockerを起動します
```
docker-compose up -d
```

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/410cb51c-82b2-4c95-c85a-fa798a5029c7.png)

3.dockerが起動したらphpmyadminの実行を確認します
ブラウザで
http://localhost:9001
を表示し
mysql_db
root
root
でphpmyadminにログインできる事を確認してください
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/d1ac66bb-14c1-621a-a437-997a663c504f.png)

![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/116c2945-cda2-6b7f-c61d-57b16729c5ed.png)

4.下記のコマンドでdockerのlaravelコンテナにログインしてlinux側で操作します
（※）linux環境にログインできるとプロンプトが>から#に変わります
```
docker exec -it laravel bash
```
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/fb6b3c9d-1b18-d75b-0817-a91191003e05.png)

5.linux環境で下記の順番でコマンドを実行します
（※）この一連のコマンドによって下記が実行されます
(1)/var/www/dummyフォルダ内でcomposer create-projectを実行
(2)/var/www/dummyフォルダの内容を/var/www/htmlフォルダにコピーします
（WindowsのファイルシステムとLinuxのvolumesファイルに振り分けられます）
(3)/var/www/htmlフォルダ以下のファイル権限を再設定してブラウザからアクセスできる様にします
```
cd /var/www
mkdir dummy
cd dummy

composer create-project --prefer-dist laravel/laravel .

(*)laravelのバージョンを11など指定したい場合は下記の様になる
composer create-project  --prefer-dist  "laravel/laravel=11.*" .

cp -r * /var/www/html
cp -r .* /var/www/html
rm -fr *
rm -fr .*
cd /var/www/html
chown -R www-data:www-data /var/www/html
exit
```
6. .htaccessファイルをhtmlフォルダにコピーしてください
7. ブラウザで
http://localhost:9000
を表示できればOKです

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123229/7ea95be7-3278-18d0-f198-67163a38b813.png)

8.この時点でhtmlフォルダに.gitignoreファイルができているので
必要があればhtmlフォルダ側に.gitignoreファイルができているので
Laravelのソース管理用に
htmlフォルダ側でもgit登録してください
（最初にgit登録したdocker用のgitではhtmlフォルダ以下は除外されていますので
htmlフォルダ以下のgit登録はこちらで行ってください）

9.初期設定やDBのマイグレーション作成時など必要に応じて下記も実行してください
下記のコマンドでdockerのapacheコンテナにログインしてlinux側で操作します
（※）linux環境にログインできるとプロンプトが>から#に変わります
```
docker exec -it laravel bash
```
linux環境に入ったら、必要に応じて下記のコマンドを実行してください
（必要が無ければ不要な操作です）
```
php artisan key:generate

php artisan migrate

php artisan db:seed
```

## ■3（プロジェクト参加者向け）既存のdocker/Laravel環境を展開する
1.git cloneなどで構築されたdocker環境をダウンロードしてください

2. .env.sampleファイルを.envファイルとしてコピーしてください

3.プロジェクトフォルダ直下にhtmlフォルダが無ければhtmlフォルダを作成し
.htaccessファイルをhtmlフォルダの中にコピーしてください

4.（最初の1回だけ実行する。docker環境の構築）
```
docker-compose build --no-cache --force-rm
```
5.dockerの起動
```
docker-compose up -d
```
6.（最初の1回だけ実行する）
```
docker exec -it laravel bash
でコンテナに入って

composer install

npm install
```
7.phpmyadminの確認
http://localhost:9001のphpmyadminは
mysql_db
root
root
でログインする

8.ブラウザで
http://localhost:9000
が表示できればOKです

（※）表示できない場合
htmlフォルダに.htaccessファイルをコピーしたかを
再確認してみてください

9.下記のコマンドでdockerを停止します
```
docker-compose stop
```
（※）コンテナごと削除したい場合は
```
docker-compose down
```
ですが、頻繁に使ってる際はstopの方がいいかと思います

10.必要があれば下記のコマンドでLinux環境に入った上で
下記のコマンドを実行してください
（必要が無ければ不要な操作です）
```
docker exec -it apache1 bash
でLinux環境に入って（必要なら）下記コマンドを実行する

php artisan key:generate

php artisan migrate

php artisan db:seed
```