以前、以下の記事でDockerを使ったローカルのWordPress環境を構築しました。


この環境を使っていたところ、管理画面だけでなくフロントページも表示が遅くなっていました。実際に応答時間を測定すると、WordPressトップページのHTMLが返ってくるまで約4.5秒かかっています。
いろいろ確認してみた結果、OPcacheやPHPそのものではなくWindows側のWordPress一式をDockerコンテナへbind mountしていた構成が大きく影響していました。
WordPress一式をnamed volumeへ置いた段階では応答時間が約100msまで短縮しました。その後、テーマやプラグインなどをWindows側からbind mountした最終構成では約1.3~1.5秒となり、変更前の約4.5秒より速い状態を維持できています。
この記事では、原因を切り分けた手順と、既存のWordPress環境をできるだけ維持したまま構成を変更した方法をまとめます。
- OS
Windows 11 Home 25H2
- Docker
Docker Desktop 4.87.0
- WordPress
7.1
- PHP
8.5.4
- MariaDB
10.5.29-MariaDB-ubu2004
WordPressの表示に4秒以上かかっていた
まず、体感ではなく実際にどの程度時間がかかっているか確認しました。PowerShellでWordPressトップページの取得時間を測定します。
Measure-Command {
Invoke-WebRequest http://localhost/ -UseBasicParsing | Out-Null
}3回測定した結果は次のとおりです。
| 回数 | TotalMilliseconds |
|---|---|
| 1回目 | 約4,473ms |
| 2回目 | 約4,471ms |
| 3回目 | 約4,556ms |
毎回ほぼ4.5秒かかっています。管理画面でも同じように待たされるため、単純にブラウザの描画だけが遅い状態ではなさそうです。
OPcacheが有効か確認する
PHPの実行が遅い原因として、最初にOPcacheを確認しました。OPcacheはコンパイル済みのPHPコードをメモリへ保持し、PHPファイルを毎回コンパイルする処理を減らす仕組みです。
Dockerコンテナ内の設定は次のコマンドで確認できます。
docker exec wp php -i | Select-String "opcache.enable"確認結果は次のとおりでした。
opcache.enable => On => On
opcache.enable_cli => Off => Off
opcache.enable_file_override => Off => Offopcache.enableはOnです。opcache.enable_cliはOffですが、これはCLIでPHPを実行した場合の設定です。Apache経由で表示するWordPressではOPcacheが有効になっています。
今回の遅さはOPcacheが無効になっていることが原因ではありませんでした。
PHPそのものが遅いのか確認する
次にWordPressを通さずPHPだけを実行した場合の応答時間を確認しました。/var/www/html/test.phpに次の単純なPHPファイルを作成します。
<?php echo "OK";PowerShellからアクセス時間を測定します。
Measure-Command {
Invoke-WebRequest http://localhost/test.php -UseBasicParsing | Out-Null
}結果は次のとおりです。
| 回数 | TotalMilliseconds |
|---|---|
| 1回目 | 約23ms |
| 2回目 | 約43ms |
| 3回目 | 約14ms |
WordPressでは約4.5秒かかっていましたが、単純なPHPファイルなら数十msで応答しています。この結果からApacheやPHP自体が4秒以上かかっているわけではなさそうです。
というワケで、確認が終わったので検証用のtest.phpは削除します。
docker exec wp rm /var/www/html/test.phpWordPress.orgへの外部通信も確認する
WordPressやプラグインは更新確認などで外部サーバーへ通信する場合があります。外部通信やDNS名前解決で待たされている可能性も考え、WordPress.orgへの通信を確認しました。
まず、名前解決を確認します。
docker exec wp php -r "var_dump(gethostbyname('api.wordpress.org'));"string(11) "66.6.42.251"IPアドレスが返ってきたため、DNS名前解決はできています。続いて、WordPress.orgへのHTTPS通信にかかる時間を測定しました。
Measure-Command {
docker exec wp php -r "file_get_contents('https://api.wordpress.org/core/version-check/1.7/');"
}Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 710
Ticks : 7106966
TotalDays : 8.22565509259259E-06
TotalHours : 0.000197415722222222
TotalMinutes : 0.0118449433333333
TotalSeconds : 0.7106966
TotalMilliseconds : 710.69663回とも約0.7秒でした。多少時間はかかっていますが、WordPressを表示するたびに約4.5秒待たされる状態を説明できるほどではありません。
ここまでの確認でPHPそのものやOPcache、DNSが主な原因とは考えにくい状態でした。
Windows側のWordPressをbind mountしていた
次に確認したのがDocker Composeのvolume設定です。元の環境ではWindows側にWordPress一式を配置していました。
D:\wordpress
└─ wordpress_filesDocker Composeではこのディレクトリ全体を/var/www/htmlへbind mountしています。
wordpress:
#(中略)
volumes:
- ./wordpress_files:/var/www/htmlこの構成にはWindowsからWordPress本体やテーマ、プラグインを直接編集できる利点があります。ですが、WordPressは1ページを表示するだけでも多数のPHPファイルを読み込みます。
先ほど確認したtest.phpは単一のファイルなので高速でしたが、WordPressではコア、テーマ、プラグインなど多くのファイルへアクセスします。
Windows側のファイルシステムとLinuxコンテナの間で大量のファイルアクセスが発生していることが、遅さに影響している可能性があります。
WordPressをnamed volumeへ置くと約100msまで高速化した
ということで、bind mountの影響を確認するためWordPress本体をDockerのnamed volumeへ置いたテスト環境を作成しました。
docker-compose.yamlでWordPress側のvolumeを次のようにします。
wordpress:
#(中略)
volumes:
- wordpress_data:/var/www/htmlファイルの末尾にもvolumeを定義します。
# (中略)
volumes:
db_data:
# 下記を追加
wordpress_data:この構成では、WordPressのファイルをWindows側ではなくDockerが管理するvolumeへ保存します。
同じようにトップページの応答時間を3回測定しました。
| 回数 | TotalMilliseconds |
|---|---|
| 1回目 | 約141ms |
| 2回目 | 約67ms |
| 3回目 | 約142ms |
Windows側へWordPress全体をbind mountしていた環境と比べると、大きな差があります。
| 構成 | 応答時間 |
|---|---|
| Windows側のWordPress一式をbind mount | 約4.5秒 |
| WordPress本体をnamed volumeへ保存 | 約0.1秒 |
この結果からWordPress全体をWindows側へ置いていた構成が大きなボトルネックになっていることが分かりました。


既存のWordPressをnamed volumeへ移行する
テスト用WordPressでは効果を確認できましたが、実際に使っているローカル環境を一から作り直す必要はありません。既存のWordPressファイルをnamed volumeへコピーすれば、現在の環境を引き継げます。
作業前にwordpress_filesのバックアップを残しておきます。
データベースは既存のdb_dataをそのまま利用するため、volumeを削除するdocker compose down -vは実行しません。
wordpress_dataを追加する
Composeファイルのvolume定義へwordpress_dataを追加します。
# (中略)
volumes:
db_data:
# 下記を追加
wordpress_data:続いて、Composeのリソースを作成します。
docker compose create作成されたvolumeは次のコマンドで確認できます。
docker volume ls今回の環境では次のvolumeが作成されました。
wordpress_wordpress_dataWindows側のWordPressをvolumeへコピーする
Windows側のD:\wordpress\wordpress_filesをnamed volumeへコピーします。
docker run --rm `
-v wordpress_wordpress_data:/dest `
-v D:\wordpress\wordpress_files:/src `
alpine sh -c "cp -a /src/. /dest/"wordpress_wordpress_dataの部分はdocker volume lsで確認した実際のvolume名に合わせます。
コピー後は、次のコマンドで内容を確認できます。
docker run --rm `
-v wordpress_wordpress_data:/data `
alpine ls -la /datawp-admin、wp-content、wp-includes、wp-config.phpなどが表示されればWordPress一式がコピーされています。
WordPress本体のmount先を変更する
WordPressサービスのvolume設定を変更します。変更前はWordPress全体をWindows側からbind mountしていました。
# (中略)
wordpress:
#(中略)
volumes:
- ./wordpress_files:/var/www/html変更後は/var/www/htmlにnamed volumeを使用します。
# (中略)
wordpress:
#(中略)
volumes:
- wordpress_data:/var/www/html設定後にコンテナを起動します。
docker compose up -d既存環境でも再度トップページの応答時間を測定しました。
| 回数 | TotalMilliseconds |
|---|---|
| 1回目 | 約123ms |
| 2回目 | 約99ms |
| 3回目 | 約89ms |
テスト環境だけでなく、既存WordPressでも約100msまで短縮できました。
named volumeへの移行後に外部ファイルの読み込みがタイムアウトした
WordPress本体をnamed volumeへ移したところ、HTMLの応答は速くなりました。一方、ブラウザではCSSやJavaScript、画像などの外部ファイルを読み込めず、画面が正しく表示されない現象が発生しました。
Chromeのデベロッパーツールで確認すると、複数の外部ファイルが読み込みに失敗していました。個別のリクエストではWebサーバーとの接続確立に約30秒かかり、そのままタイムアウトしています。


ファイルが存在しない場合に返される404エラーではなく接続確立に時間がかかったまま失敗しているため、named volume内にファイルがないことが直接の原因とは判断できません。テーマだけでなくWordPress本体やプラグインのファイルも失敗しており、特定のテーマディレクトリだけで発生している問題ではなさそうです。
この画面だけではWebサーバー、コンテナとの接続経路など、どの段階に原因があるかまでは特定できませんでした。ひとまず、themesとpluginsをWindows側からbind mountすると外部ファイルを再び読み込めるようになりました。ただ、この変更で解消した理由はヨクワカリマセンデシタ。
必要なファイルをWindows側へbind mountする
テーマファイル・プラグインファイル
外部ファイルとして参照する可能性のあるthemesやpluginsのディレクトリ全体をWindowsにマウントします。テーマ(子テーマがある場合は子テーマ)のfunctions.phpなどもWindows側で編集する可能性があるので、外部参照はされませんがWindows側にあったほうが便利です。
wordpress:
#(中略)
volumes:
# テーマとプラグインのディレクトリを追加
- ./wordpress_files/wp-content/plugins:/var/www/html/wp-content/plugins
- ./wordpress_files/wp-content/themes:/var/www/html/wp-content/themes編集する可能性のあるファイル
上記のファイルの他にwp-config.phpなど編集する可能性のあるファイルもWindows側に配置してWindowsで編集できるようにしたほうがスムーズに運用できますよね。同じディレクトリにほかにほしいファイルがいまのところなかったので、wp-config.phpはファイル単位で指定してあげることにしました。
wordpress:
#(中略)
volumes:
# wp-config.phpをファイル単体で追加
- ./wordpress_files/wp-config.php:/var/www/html/wp-config.php

Composeファイルの今回変更分をまとめると下記のようになりました。
wordpress:
#(中略)
volumes:
- wordpress_data:/var/www/html
- ./wordpress_files/wp-content/plugins:/var/www/html/wp-content/plugins
- ./wordpress_files/wp-content/themes:/var/www/html/wp-content/themes
- ./wordpress_files/wp-config.php:/var/www/html/wp-config.php
volumes:
db_data:
wordpress_data:bind mountを追加するとnamed volume内の同じパスにある内容はマウント中に隠れ、Windows側のファイルが使われます。
コンテナを起動する前にwordpress_files/wp-content/plugins、wordpress_files/wp-content/themes、wordpress_files/wp-config.phpへ必要なファイルが存在することを確認してください。
最終構成で応答時間を再確認する
テーマ、プラグイン、wp-config.phpをWindows側からbind mountした状態でも、トップページの応答時間を3回測定します。
Measure-Command {
Invoke-WebRequest http://localhost/ -UseBasicParsing | Out-Null
}| 回数 | TotalMilliseconds |
|---|---|
| 1回目 | 約1,309ms |
| 2回目 | 約1,422ms |
| 3回目 | 約1,522ms |
WordPress一式をnamed volumeへ置いた構成より応答時間は長くなりましたが、外部ファイルを読み込める状態で約1.3~1.5秒でした。WordPress全体をWindows側からbind mountしていた約4.5秒と比べると、応答時間は短縮されていますね。
DockerのWordPressが遅いときはmount先を見直す
Dockerで動かすWordPressが遅い場合はPHPやOPcacheだけでなく/var/www/html のmount元も確認してみてください。今回の環境ではWordPress一式をWindows側からbind mountしていた構成がボトルネックとなっていました。WordPress本体をnamed volumeへ移すことでHTMLの応答時間を約4.5秒から約1.5秒まで短縮できています。
ですが、すべてのファイルをnamed volumeへ置くとWindows側から編集しにくくなります。今回はWordPress本体の大部分をnamed volumeへ置きthemes、plugins、wp-config.phpだけをWindows側からbind mountしました。テーマのCSSやJavaScriptなどをWebサーバーから配信しつつ、テーマやプラグイン、設定ファイルはWindows側で編集できる構成です。
ローカルWordPressだけが極端に遅い場合は単純なPHPファイルとWordPressの応答時間を比較したうえでDocker Composeのvolumes設定を確認すると原因を絞り込みやすくなります。WordPress全体をbind mountするのではなく]Windows側で扱う必要があるファイルだけを切り分けるのがポイントです。
ローカル環境の改善後にWordPress本体の更新・セキュリティ・プラグイン開発も確認したい場合は、WordPressまとめから目的別に探せます。





