はじめに
昨今では開発環境と言ったらDockerという感じかと思いますが、自分が働く現場ではXAMPPをメインで使用しています。
現場で複数のPHPプロジェクトを見ることになったので、既存プロジェクト(以下 legacy-app、ポート81で稼働中)と、新しいプロジェクト(以下 sample-app)も同時に動かす必要が出ました。
最初は「htdocsにフォルダ置くだけでいけるかな~」くらいに考えてたんですが、実際やってみるとポート競合やApacheそのものが起動しなくなる沼にハマったので、今回は備忘録として切り分け手順のメモとして書こうと思います。
意外とレガシーな現場だとまだXAMPPが残ってると思うので、そういった方々へ有用なものとなればいいなと思います。
結論
先に結論から。httpd-vhosts.conf に複数の <VirtualHost> ブロックを追記すれば、ポートやドメインを分けて複数のLaravelプロジェクトを同時に動かせます。
ただし追記する前に、以下の3点を確認しておかないとApacheそのものが起動しなくなって原因切り分けに時間を溶かします。(というか溶かしました。笑)
-
httpd.confのInclude conf/extra/httpd-vhosts.confが有効になっているか - 使いたいポート(81番など)が
Listenで定義されているか - そのポートを他のプロセス(自分の場合はIIS)が先に掴んでいないか
環境・前提
- OS: Windows
- XAMPP(Apache:
Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.2.11) - 既存プロジェクト
legacy-appはポート81・ドメインlegacy.example.comで稼働中 - 新規プロジェクト
sample-appをポート80で追加する想定
1. まずhtdocsに複数プロジェクトを置いてみる
一番手軽なのは、htdocs 配下に別フォルダとして置くだけの方法です。
C:\xampp\htdocs\legacy-app
C:\xampp\htdocs\sample-app
この場合、Laravelなら public までパスを指定してアクセスします。
http://localhost/legacy-app/public
http://localhost/sample-app/public
一旦これで動作確認まではできるんですが、毎回URLに /public を付けるのが煩わしいし、既存プロジェクトが独自ドメイン運用だったのでこの方法だと再現できませんでした。というわけでVirtualHostを使う方針に切り替えました。
2. httpd-vhosts.confでVirtualHostを追加する
設定ファイルの場所はここ。
C:\xampp\apache\conf\extra\httpd-vhosts.conf
既存プロジェクト(ポート81)はそのまま残しつつ、新規プロジェクト用のVirtualHostを追記。
# 既存プロジェクト(そのまま維持)
<VirtualHost *:81>
ServerName legacy.example.com
DocumentRoot "C:/xampp/htdocs/legacy-app/public"
<Directory "C:/xampp/htdocs/legacy-app/public">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
# 以下はsample-appで利用する
<VirtualHost *:80>
ServerName sample-app.local
DocumentRoot "C:/xampp/htdocs/sample-app/public"
<Directory "C:/xampp/htdocs/sample-app/public">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
【重要】ポート番号を追加した場合、httpd.conf 側にも Listen の記述が必要。
Listen 80
Listen 81
3. httpd.confのInclude設定を確認する
httpd-vhosts.conf を編集しても、そもそも読み込まれていなければ意味がないので、httpd.conf を開いて以下の行を確認します。
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
#Include conf/extra/httpd-vhosts.conf のように先頭に # が付いていたらコメントアウトされている状態なので、外して有効化します。編集後はApacheの再起動が必要です。
4. hostsファイルにドメインを追加する
独自ドメイン風のServerNameでアクセスしたい場合は、Windowsのhostsファイルにも追記します。
C:\Windows\System32\drivers\etc\hosts
127.0.0.1 sample-app.local
127.0.0.1 legacy.example.com
編集には管理者権限が必要です。保存後はブラウザを一度完全に閉じてから開き直すと確実でした。
5. ServerNameを変えたのに反映されない場合のチェックリスト
一度、既存プロジェクトのServerNameを試しに変更してみたんですが、全然反映されなかったことがありました。原因になりやすいのは以下の4つです。
- httpd-vhosts.confがそもそも読み込まれていない(2.のInclude漏れ)
- Listenが定義されていない(該当ポートをApacheが無視する)
- 同じポートに複数のVirtualHostがあり、先に読み込まれた方が優先されている(XAMPPのデフォルトVirtualHostが残っているとよく起きる)
-
ブラウザのアクセス先が実はServerNameではなくIP:ポートのまま(
localhost:81にアクセスしていれば、ServerNameを変えても見た目上は変化しない)
上から順に確認していけば大体特定できます。
ハマったところ:vhostを追記したらApacheそのものが起動しなくなった
VirtualHostを追記して保存したあと、Apacheが Apache shutdown unexpectedly を吐いて起動しなくなりました。
しかもerror.logを見ても何も出てなくて、「どこ見ればいいの?」ってなりました。
切り分け手順
まずポートがそもそもLISTENしているか確認しました。
netstat -aon | find "80"
結果、ポート80はLISTENしておらず、代わりに見慣れないポート(61480)がLISTENしている状態でした。
これはApacheが80番を確保できず、勝手に別ポートへ逃げようとした挙動みたいです。
つまりポート80が別プロセスに奪われている可能性が濃厚とのことでした(AIとの相談)。
犯人を特定するため、LISTENしているPIDを確認。
tasklist /FI "PID eq 1668"
結果は services.exe でした。
ただ、services.exe 自体がポートを直接掴むことはないので、その配下で動いている何かが本当の犯人らしいです。
Windowsでポート80を奪いがちなサービスの代表格がIIS(World Wide Web Publishing Service)で、今回もこれが原因だったみたい。
対処
net stop w3svc
停止したら無事Apacheが起動しました。毎回止めるのが面倒な場合は自動起動自体を無効化できるみたいです。
sc config w3svc start= disabled
補足:XAMPPコントロールパネルのポート表示は起動確認に使える
XAMPPコントロールパネルのApache横に並ぶポート番号は、実際にLISTENしているポートです。80/443だけでなく、VirtualHostで追加した81や82なども正しくLISTENできていれば表示されます。
逆に言うと、追加したはずのポートがここに表示されていない場合は、Listen の定義漏れかポート競合を疑うサインです。ブラウザでアクセスする前のひと目チェックとして使えます。
おまけ:プロジェクトごとにPHPのバージョンを分けたい場合
複数プロジェクトを運用してると「このプロジェクトだけPHP7系で動かしたい」というケースも出てきます。ただXAMPPは1つのApacheに対して1つのPHPしか読み込めない構造(LoadModule php_module が1本しか指定できない)なので、PHP7とPHP8のプロジェクトを同時運用することはできません。
この点についてはLaragonやDocker、あるいはXAMPPを複数インストールしてポートを分ける案を教えてもらいましたが、自分ではまだ試していないので未検証です。複数バージョンが本当に必要になったタイミングで別途試してみようと思ってます。
まとめ
| 確認項目 | 場所 |
|---|---|
| VirtualHostの追記 | httpd-vhosts.conf |
| Include有効化 | httpd.conf |
| Listenポート定義 | httpd.conf |
| ドメイン紐付け |
hosts ファイル |
| ポート競合の犯人特定 |
netstat -aon → tasklist /FI "PID eq ..."
|
vhostの設定自体はシンプルですが、Apacheが起動しなくなったときに「設定ミスなのかポート競合なのか」を切り分けられるかどうかで詰まる時間がだいぶ変わってきます。ハマったら、まずは netstat でポートの状況を確認するところから始めるのがよさそうでした。