はじめに
👇前回は、Azure 仮想マシンで Docker Desktop を動かす方法を紹介しました。
今回は 「Azure SQL Database を使った WordPress 環境を Docker コンテナで構築する」 ために行ったことと、実運用で必要だった調整ポイントをまとめます。
WordPress は通常 MySQL を利用しますが、今回は SQL Server を使いたかったため、SQL Server 対応版の Project Nami を採用しました。
Project Nami とは
Project Nami は、WordPress を Microsoft SQL Server (Azure SQL Database) 上で動かすために WordPress コアを改修したオープンソースの派生版です (2016 年公開)。MySQL 依存の部分を置き換え、クラウド環境でも WordPress を SQL Server で利用可能にします。
主な特徴
- WordPress の基本機能をサポート (投稿、テーマ、管理画面 など)
- SQL Server 2012 以降に対応 (OFFSET FETCH などで MySQL の LIMIT 相当を実現)
- Azure との親和性 (クラウド利用を想定)
- プラグイン互換性はケースバイケース (必要に応じてパッチ適用の前提)
なぜ Project Nami をコンテナ化したのか?
SQL Server(Azure SQL Database)が長年の得意分野であり、Project Nami を好んで利用しています。
そして以前、以下の記事で PHP のバージョン対応に触れまして...
ここで取り上げた PHP 8.1 が 2025 年末でサポート終了 (EOL) してしまうので、更なる恒久的な対応を施さなければなりません! ![]()
前述の投稿で紹介したリポジトリは、2025 年 6 月に PHP 8.3 にアップデート済みです。Azure App Service on Windows で PHP を使いたい場合はそちらも選択肢になります (ご利用は自己責任で)。
また今回は、コンテナ開発に再挑戦してみようと思います。
作業環境
- Docker Desktop 4.55.0
- Docker Engine 29.1.3
- Dockerfile 0.30.1-desktop.1
- Microsoft Windows Server 2025 Datacenter Azure Edition
- OS version: 10.0.26100 N/A Build 26100
- VM size: Standard D4ads v5
- WSL 2
アーキテクチャ構成図
検証環境として、必要最小限のリソースで用意しました。
- 開発言語:PHP 8.3.x
- Web サーバー:Apache 2.4.x
- アプリ:Project Nami(WordPress 派生版)
コンテナ化のポイント
今回の Dockerfile は、単に Project Nami を動かすだけでなく、 「SQL Server で安定して動作する WordPress 環境を、Azure 上で運用できるように最適化する」 ことを目的に構成しています。
ポイントは大きく 5 つあります。
-
Project Nami を動かすための必須セットアップ
SQL Server ドライバの導入、Project Nami 本体の展開、class-wpdb.php の互換パッチなど -
WordPress を実運用するための追加設定
日本語ロケール、HTTPS 対応、.htaccess 生成、Apache/PHP の調整など -
Cocoon テーマの SQL Server 互換修正
MySQL 固有のGROUP_CONCAT()を SQL Server のSTRING_AGG()に置き換えるなど、テーマ側の SQL 文を修正 -
プラグインの自動インストールと互換パッチ
複数のプラグインを ZIP から自動展開し、必要に応じて SQL Server 互換の修正を適用 -
コンテナとしての最適化
イメージサイズ削減、ログの標準出力化、SSH 対応、パーミッション調整など
1. Project Nami を動かすための必須セットアップ
Project Nami は「WordPress を SQL Server で動かす」ために作られた派生版です。そのため、通常の WordPress コンテナとは異なり、SQL Server 用の PHP ドライバや ODBC ランタイムの導入、Project Nami 固有のファイル修正が必要になります。
ここでは、コンテナ内で Project Nami を正しく動作させるために行った“必須セットアップ”をまとめます。
(1) SQL Server 用ドライバ (ODBC / PHP 拡張) の導入
Project Nami は MySQL ではなく SQL Server を利用するため、PHP から SQL Server に接続できる環境を整える必要があります。
今回のコンテナでは、以下のコンポーネントをインストールしています。
- msodbcsql17 (Microsoft ODBC Driver for SQL Server)
- unixODBC-dev (ODBC ランタイム)
- pdo_sqlsrv / sqlsrv (PHP 拡張)
これらは Microsoft の公式リポジトリを追加し、apt 経由でインストールしています。
特に pdo_sqlsrv と sqlsrv は Project Nami の動作に必須で、これがないと WordPress のインストール画面すら表示されません。
WordPress を SQL Server で動かすための “心臓部” となるセットアップです。
(2) Project Nami 本体の展開
Project Nami は WordPress 本体をベースに SQL Server 対応を施したフォークです。
GitHub で公開されている ZIP をダウンロードし、コンテナ内の /var/www/html に展開しています。
(3) class-wpdb.php の SQL Server 互換パッチ (Issue #515 対応)
Project Nami 6.2 系では、WordPress 本体の更新取り込みに伴い、Unicode 文字(絵文字・日本語)が SQL Server で正しく保存されない問題が発生していました。
原因は、SQL Server に文字列を渡す際に必要な N'...' (NVARCHAR リテラル) 付与処理が削除されてしまったことです。
この問題は GitHub Issue #515 で報告されており、修正 PR (#516) が取り込まれるまでの間は、Dockerfile 内で wp-includes/class-wpdb.php に対して互換パッチを適用しています。
/*
* Unquoted strings for backward compatibility (dangerous).
* First, "numbered or formatted string placeholders (eg, %1$s, %5s)".
* Second, if "%s" has a "%" before it, even if it's unrelated (e.g. "LIKE '%%%s%%'").
*/
if ( true !== $this->allow_unsafe_unquoted_parameters
/*
* Note: str_ends_with() is not used here, as this file can be included
* directly outside of WordPress core, e.g. by HyperDB, in which case
* the polyfills from wp-includes/compat.php are not loaded.
*/
|| ( '' === $format && '%' !== substr( $split_query[ $key - 1 ], -1, 1 ) )
) {
- $placeholder = "'%" . $format . "s'";
+ $placeholder = "N'%" . $format . "s'";
}
このパッチがないと、記事本文やタイトルに含まれる絵文字が ? に化けてしまいます。
(4) wp-config.php の自動生成(Azure SQL Database 対応)
Project Nami は通常の WordPress と同様に wp-config.php を必要としますが、SQL Server を利用するため、以下の設定を環境変数から自動生成しています。
- DB_HOST: サーバー名 (Azure SQL の FQDN: xxxxx.database.windows.net)
- DB_NAME: データベース名
- DB_USER: ユーザー名 (ユーザー名@サーバー名 の形式)
- DB_PASSWORD: パスワード
- SQL Server 固有の接続オプション
define('DB_NAME', getenv('DB_NAME') ?: 'hogedb');
define('DB_USER', getenv('DB_USER') ?: 'user');
define('DB_PASSWORD', getenv('DB_PASSWORD') ?: 'p@ssw0rd!');
define('DB_HOST', getenv('DB_HOST') ?: 'hogeserver');
これにより、コンテナ起動直後から Azure SQL Database に接続できる状態になります。
まとめ
Project Nami をコンテナで動かすためには、通常の WordPress とは異なるセットアップが必要です。
- SQL Server 用の ODBC / PHP ドライバを導入する
- Project Nami 本体を展開する
- class-wpdb.php の互換パッチを適用する
- wp-config.php を SQL Server 向けに自動生成する
これらの処理を Dockerfile に組み込むことで、コンテナを起動するだけで Project Nami が動作する環境を実現しています。
2. WordPress を実運用するための追加設定
Project Nami をコンテナ上で動かすだけなら、前節で紹介したセットアップで十分です。しかし、実際に Web サイトとして運用するには、WordPress とコンテナの両方を安定して動かすための追加設定が欠かせません。
ここでは、今回の環境で行った「実運用に必要な追加設定」をまとめます。
(1) 日本語ロケールの導入 (WordPress の多言語対応)
WordPress 本体は英語版がデフォルトのため、日本語環境で利用する場合は .mo ファイルを追加する必要があります。
Dockerfile では、WordPress 日本語版から必要な翻訳ファイルを取得し、wp-content/languages に配置しています。
これにより、初期セットアップ直後から管理画面が日本語で表示され、テーマやプラグインの翻訳も正しく適用されます。
(2) HTTPS リバースプロキシ対応 (X‑Forwarded‑Proto)
Azure App Service for Containers では、HTTPS の終端は App Service 側で行われ、コンテナ内部には HTTP でリクエストが届きます。
そのため、WordPress に対して
- 実際のアクセスは HTTPS である
- リダイレクトや URL 生成も HTTPS にすべき
という情報を伝える必要があります。
Dockerfile では wp-config.php に以下のような処理を追加し、X‑Forwarded‑Proto を正しく解釈させています。
if (!empty($_SERVER["HTTP_X_FORWARDED_PROTO"]) && strpos($_SERVER["HTTP_X_FORWARDED_PROTO"], "https") !== false) {
$_SERVER["HTTPS"] = "on";
$_SERVER["SERVER_PORT"] = 443;
}
これにより、管理画面の混在コンテンツ警告や、HTTPS → HTTP への誤ったリダイレクトが発生しなくなります。
(3) Apache / PHP の運用向けチューニング
App Service for Containers で安定運用するため、Web サーバーと PHP の設定も調整しています。
Apache の設定
-
.htaccessを自動生成.htaccess<IfModule mod_rewrite.c> RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> -
AllowOverride Allを有効化 - mod_rewrite を有効化
PHP の設定
default_charset = UTF-8- opcache の推奨設定を追加 (パフォーマンス向上)
/usr/local/etc/php/conf.d/opcache-recommended.ini
opcache.enable=1 opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.validate_timestamps=0 opcache.revalidate_freq=0
これらの設定により、WordPress の動作が安定します。
まとめ
WordPress(Project Nami)を実運用するためには、単に動かすだけでは不十分で、以下のような追加設定が欠かせません。
- 日本語ロケール
- HTTPS リバースプロキシ対応
- Apache / PHP の運用設定
これらを Dockerfile に組み込むことで、コンテナを起動するだけで実運用可能な WordPress 環境を構築できます。
3. Cocoon テーマの SQL Server 互換修正
今回のサイトでは Cocoon テーマを利用していますが、Cocoon は MySQL 前提の SQL 文を多く含んでいます。
特に問題となるのが MySQL 固有の関数 GROUP_CONCAT() を使用している箇所です。
SQL Server には GROUP_CONCAT() が存在しないため、Cocoon の一部機能がエラーになり、ページが正しく表示されなくなります。
(1) 代表的な問題: GROUP_CONCAT() → STRING_AGG() への置換
SQL Server で同等の処理を行うには、STRING_AGG() を使う必要があります。
- $res = $wpdb->get_results("SELECT DISTINCT GROUP_CONCAT(post_id) AS ids FROM {$wpdb->prefix}postmeta WHERE (meta_key = '{$meta_key}') AND (meta_value = 1)");
+ $res = $wpdb->get_results("SELECT STRING_AGG(post_id, ',') AS ids FROM {$wpdb->prefix}postmeta WHERE (meta_key = '{$meta_key}') AND (meta_value = 1)");
Cocoon のコードには GROUP_CONCAT() を使ったクエリが複数存在するため、Dockerfile 内で自動置換しています。
(2) テーマ内の SQL 文の修正
Cocoon の一部ファイルでは、SQL 文が PHP コード内に直接埋め込まれているため、単純な置換だけでは対応できない箇所もあります。
そのため、以下のような対応を行いました。
- 問題のあるファイルをビルドコンテキストに用意
- Dockerfile で該当ファイルを上書き
- SQL Server で動作するようにクエリを修正
- 必要に応じて
CASTやCONVERTを追加
これにより、Cocoon の機能(関連記事、タグ一覧、人気記事など)が SQL Server 上でも正常に動作するようになります。
(3) なぜテーマ修正が必要なのか
Project Nami は WordPress 本体を SQL Server で動かせるように最適化していますが、テーマやプラグインの SQL 文までは自動変換してくれません。
そのため、
- MySQL 固有の関数
- MySQL 固有の構文
- 暗黙の型変換
などを使っているテーマは、SQL Server では動作しないケースがあります。
Cocoon は高機能ゆえに SQL を多用しており、今回のような修正が必要になりました。
(4) 修正を Dockerfile に組み込むメリット
テーマ修正を Dockerfile に組み込むことで
- コンテナをビルドするだけで修正済み Cocoon が完成する
- 環境差異による不具合が発生しない
- テーマ更新時に差分管理がしやすい
- CI/CD パイプラインに組み込みやすい
といったメリットがあります。
特に、Azure App Service for Containers のような環境では、「コンテナがそのまま本番環境」 になるため、Dockerfile に修正を集約するのは非常に合理的です。
まとめ
Cocoon は MySQL 前提のテーマであるため、Project Nami(SQL Server)環境ではそのままでは動作しません。
今回のコンテナ化では、以下のような SQL Server 互換修正を行いました。
-
GROUP_CONCAT()をSTRING_AGG()に置換 - SQL 文を含むファイルを上書き修正
- Dockerfile に修正処理を組み込み、自動
これにより、Cocoon を SQL Server 上でも安定して利用できるようになりました。
4. プラグインの自動インストールと互換パッチ
WordPress を実運用する場合、テーマだけでなく 複数のプラグインを組み合わせてサイトを構築することが一般的です。しかし、Project Nami (SQL Server) 環境では、プラグインによっては MySQL 固有の SQL 文や関数を使っているため、そのままでは動作しないケースがあります。
そこで今回のコンテナ化では、必要なプラグインを Dockerfile 内で自動インストールし、さらに SQL Server で動作しない部分をパッチ適用する仕組みを組み込みました。
(1) プラグインの自動インストール
実運用で利用するプラグインは、Dockerfile 内で ZIP をダウンロードし、コンテナビルド時に展開しています。
- 例:
- All In One WP Security
- WP Super Cache
- XML Sitemap Generator
- Content Views
- Meta Slider
- Pz-LinkCard
これにより、コンテナを起動するだけで 必要なプラグインが揃った状態になります。
なぜ自動インストールにしたのか
- 本番環境での手作業をなくすため
- CI/CD パイプラインで再現性を確保するため
- プラグイン更新時の差分管理を容易にするため
- App Service for Containers の「コンテナ=本番環境」という特性に合わせるため
Dockerfile に集約することで、環境差異による不具合を防げます。
(2) SQL Server 互換パッチの適用
一部のプラグインは MySQL 前提で SQL 文を書いているため、Project Nami ではエラーになることがあります。
- 例:
- MySQL 固有の関数(
GROUP_CONCAT、FIND_IN_SETなど) - 暗黙の型変換
-
LIMITの扱い - バインドパラメータの違い
- MySQL 固有の関数(
こうした問題に対して、Dockerfile では以下のような対応を行っています。
- 問題のあるファイルをビルドコンテキストに用意
- コンテナビルド時に該当ファイルを上書き
- SQL Server で動作するようにクエリを修正
- 必要に応じて
CASTやCONVERTを追加
これにより、プラグインが SQL Server 上でも安定して動作するようになります。
(3) プラグイン互換パッチを Dockerfile に組み込むメリット
-
環境差異がなくなる
→ 本番・ステージング・ローカルが完全に同じ状態に -
再現性が高い
→ コンテナをビルドするだけで同じ環境が作れる -
更新時の差分管理が容易
→ プラグイン更新で SQL 文が変わった場合も追跡しやすい -
CI/CD と相性が良い
→ GitHub Actions などで自動ビルド可能
特に Project Nami のような特殊環境では、「動く状態を Dockerfile に閉じ込める」 ことが非常に重要です。
まとめ
Project Nami (SQL Server) 環境では、プラグインが MySQL 前提で書かれていることが多く、そのままでは動作しないケースがあります。
今回のコンテナ化では、
- プラグインの自動インストール
- SQL Server 互換パッチの適用
- Dockerfile による再現性の確保
を行うことで、コンテナを起動するだけで実運用可能な WordPress 環境を実現しました。
5. コンテナとしての最適化
Project Nami(WordPress)を動かすだけなら前章までの設定で十分ですが、実際に Azure App Service for Containers 上で安定運用するには、コンテナそのものを最適化する作業が欠かせません。
ここでは、今回の Dockerfile に組み込んだ「コンテナとしての最適化ポイント」を紹介します。
(1) イメージサイズ削減 (不要ファイルの徹底削除)
Docker イメージは小さいほど
- デプロイが速い
- スケールアウトが速い
- セキュリティリスクが減る
というメリットがあります。
今回の Dockerfile では、以下のような最適化を行っています。
- apt キャッシュの削除
- man / doc / static library の削除
- Composer キャッシュ削除
- 一時ファイルの削除
- 不要なテーマ・プラグインの削除
これにより、巨大になりがちな WordPress コンテナでも、運用に必要な最小限のサイズに抑えています。
(2) Apache ログと PHP エラーログを stdout / stderr にリダイレクト
Azure App Service for Containers では、コンテナ内部のログを 標準出力 (stdout) と標準エラー (stderr) に流すことで、App Service のログ機能と統合できます。
そのため、Dockerfile では Apache のログ設定を以下のように変更しています。
- access.log → stdout
- error.log → stderr
RUN ln -sf /proc/self/fd/1 /var/log/apache2/access.log \
&& ln -sf /proc/self/fd/2 /var/log/apache2/error.log \
&& sed -i 's|ErrorLog ${APACHE_LOG_DIR}/error.log|ErrorLog /proc/self/fd/2|g' /etc/apache2/apache2.conf \
&& sed -i 's|CustomLog ${APACHE_LOG_DIR}/access.log combined|CustomLog /proc/self/fd/1 combined|g' /etc/apache2/apache2.conf
また、PHP エラーログも stderr にリダイレクトします。
log_errors = On
error_log = /proc/self/fd/2
これにより、App Service の「ログストリーム」や「Log Analytics」でログを一元管理できます。
(3) SSH 対応でデバッグ可能に
Azure App Service for Containers では、SSH コンソールからコンテナ内部に入れると非常に便利です。
そのため、Dockerfile では以下を設定しています。
- openssh-server のインストール
-
appsvcユーザーの作成 - sshd_config の調整
- 2222 ポートの EXPOSE
- entrypoint.sh で
sshd→Apacheの順に起動
これにより、App Service の「開発ツール > SSH」から直接コンテナにアクセスでき、トラブルシュートが格段にラクになります。
(4) パーミッションの最適化
WordPress は wp-content 配下にファイルを書き込むため、適切なパーミッション設定が必要です。
Dockerfile では、
- Apache 実行ユーザー (www-data) への所有権変更
- キャッシュディレクトリの作成
- プラグインが必要とする書き込み権限の付与
などを行い、コンテナ起動直後から WordPress が正常に動作する状態を作っています。
(5) エントリーポイント (entrypoint.sh) の整理
コンテナ起動時に
- SSHD の起動
- Apache の起動
- 必要な初期化処理
を順番に行うため、独自の entrypoint.sh を用意しています。
これにより、App Service のライフサイクルに合わせてコンテナが安定して起動するようになります。
まとめ
コンテナは「動けばいい」だけでは不十分で、運用を考えると 軽量・安定・デバッグしやすい ことが重要です。
今回のコンテナでは、
- イメージサイズ削減
- ログの標準出力化
- SSH 対応
- パーミッション最適化
- エントリーポイントの整理
といった最適化を行い、Azure App Service for Containers 上で安定して動作する WordPress 環境を実現しています。
デプロイ
以下のドキュメントの手順に従って、Azure Container Registry にコンテナ イメージをプッシュし、App Service の「デプロイ > デプロイ センター」にて、コンテナ イメージをプルします。
その後、WordPress にログインし、以下の設定操作を行います。
- ダッシュボード > 更新 ページで [翻訳を更新] をクリックする
- Cocoon 設定 にて、以下のように設定する
- アクセス集計: 「アクセス集計を有効にする」にチェックを付けない
※有効にすると、レスポンスがすごく重くなる - 高速化
- キャッシュの有効化: 「キャッシュを有効にする」にチェックを付ける
- CSS 縮小化: 「CSS を縮小化する」にチェックを付ける
- JavaScript 縮小化: 「JavaScript を縮小化する」にチェックを付ける
- 遅延読み込み: 「Lazy Load を有効にする」にチェックを付ける
- Googleフォント: 「Googleフォントの非同期読み込みを有効にする」にチェックを付ける
- アクセス集計: 「アクセス集計を有効にする」にチェックを付けない
- 設定 > WP Super Cache にて、以下のように設定する
- キャッシング: 「キャッシング利用 (推奨)」を選択して [ステータスを更新] をクリック
- 設定 > XML-Sitemap にて、以下の操作を行う
- [変更を保存] をクリック
サイトマップインデックスファイル (sitemap.xml) を作成
- [変更を保存] をクリック
さいごに
今回は Project Nami (SQL Server対応版 WordPress) を Docker コンテナ化し、Azure App Service for Containers 上で運用するためのポイントをまとめました。
通常の WordPress コンテナとは異なり、SQL Server ドライバの導入やテーマ・プラグインの互換パッチ、HTTPS対応など、細かな調整が必要でしたが、これらを Dockerfile に集約することで「ビルド=運用可能な環境」 を実現できました。
このアプローチのメリットは、再現性と保守性です。CI/CD パイプラインに組み込めば、更新やスケールにも強い構成になります。
