手元の作業環境は、ずっと XAMPP を使っています。ふだんの開発は PHP 8.3 で動かしていますが、保守を続けているお客さんのサイトの中には、PHP 5.6 や 7.3 でしか動かない古いものもあります。そういうサイトを見るたびに、XAMPP の PHP のフォルダを入れかえて確認していました。
ところが XAMPP の標準の形では、PHP は 1 つだけです。古いサイトを見ているあいだは、ほかの PHP 8 のサイトも、PHP で動かしている小さなツールも全部止まってしまいます。今日もちょうどそうなって、作業が止まりました。こういうことが何度もあったので、古い PHP だけを Docker に任せる形に変えてみました。
Docker だけにしなかった理由
最初は「全部 Docker に移す」ことも考えました。ただ、XAMPP は長く使っていて慣れていますし、ほとんどのサイトは PHP 8.3 で困っていません。全部を移すと、http と https の口や証明書、サイトごとのアドレスの設定を、Docker の側で一から用意し直すことになります。
そこで、XAMPP はそのまま入口として使い、古い PHP が要るサイトだけを Docker に回すことにしました。ブラウザーから見えるアドレスは今までと同じで、裏でどちらが処理するかだけを変える形です。
ホスト名で振り分ける
形はとても単純です。XAMPP の Apache が、サイトの名前(ホスト名)ごとに行き先を決めます。

どちらにするかは、XAMPP のバーチャルホストの書き方だけで決まります。今までどおり DocumentRoot を書けば XAMPP で動き、ProxyPass を書けば Docker の箱に回ります。
<VirtualHost *:80>
ServerName old-site.local
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8056/
ProxyPassReverse / http://127.0.0.1:8056/
</VirtualHost>
ProxyPass を使うには、XAMPP の Apache の設定ファイル(httpd.conf)で、mod_proxy と mod_proxy_http を読み込む行の「#」を外しておきます。ProxyPreserveHost を付けているので、箱の中にも「old-site.local へのアクセス」として届きます。箱の中の Apache にも同じ名前のバーチャルホストを置いておけば、1 つの箱で複数の古いサイトを同時に動かせます。PHP のバージョンは、回す先のポート(箱)で選びます。
うまく動かすために足したこと
実際に動かしてみると、そのままではいくつか困ることがありました。どれも、XAMPP で直接動かしていたときと同じ見え方にするための調整です。
1 つ目は https です。XAMPP で https を受けて箱に http で回すと、「https でなければ https へ転送する」という書き方の .htaccess があるサイトで、転送がくり返されてしまいます。箱にも https の口を作り、XAMPP からは https のまま回すようにしました。
<VirtualHost *:443>
ServerName old-site.local
SSLEngine on
(XAMPP の証明書の 2 行)
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPreserveHost On
ProxyPass / https://127.0.0.1:8456/
ProxyPassReverse / https://127.0.0.1:8456/
</VirtualHost>
2 つ目はアクセス元の IP です。箱の中から見ると、相手は Docker の中の IP になるので、「127.0.0.1 からだけ許可」という制限のあるページが開けなくなりました。Apache の remoteip で、XAMPP が付ける X-Forwarded-For から元の IP に戻すようにしています。どこから来た X-Forwarded-For を信用するか(Docker の中の IP の範囲)も書いておきます。
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 172.16.0.0/12
3 つ目は証明書です。はじめは箱の https の口にも、XAMPP に付いてきた自己署名の証明書を使おうとしました。ところがこの証明書は鍵が短く、新しい箱(PHP 7.3)の OpenSSL が受け付けず、箱が起動しませんでした。そこで箱には箱だけの証明書を作りました。また XAMPP の証明書は期限も切れていたので、XAMPP から箱へ回すときは、相手の証明書を確認しない設定(上の SSLProxyVerify none・SSLProxyCheckPeerExpire off など)にしています。どれも PC の中だけの通信なので、ここは割り切りました。
ほかには、データベースは今までと同じ LAN の中の DB サーバーをそのまま使い、メールは箱の中で送らずに捨てる設定にしました。古いサイトから本物のお客さんにメールが出てしまうのが、いちばん怖いからです。
使ってみて
これで、古いサイトを見ているあいだも、ふだんの作業が止まらなくなりました。アドレスもプログラムの設定も XAMPP のときのままなので、使う側は何も変わりません。サイトの PHP を上げられたら、XAMPP のその 1 か所を ProxyPass から DocumentRoot に戻すだけで済みます。
PHP のバージョンアップの確認にも
お客さんのサイトの PHP のバージョンアップの確認にも使えそうです。同じサイトを 5.6、7.3、8.3 の順に回して、どこで動かなくなるかを確認できます。Docker だけで組むより、慣れた XAMPP を残したほうが、結果的に便利な形になったと思います。
今回の設定は、AI(Claude)と相談しながら組み立てました。https の転送や IP の制限でつまずいたところも、原因をログから一緒に追いかけて、その日のうちに動くところまで持っていけました。