2026年7月29日

2026年7月29日

Blue-GreenデプロイメントをWordPressで実装する方法

Blue-Green デプロイメントは、本番と同じ構成の環境を2つ(Blue と Green)用意し、待機側に新しい版を入れて確認してから、リバースプロキシやロードバランサーの振り分け先を切り替える方法です。WordPress でも実装できますが、データベース・アップロードファイル・WP-Cron を2つの環境でどう扱うかを決めないと、切り替えた瞬間に投稿や注文が消えるといった事故につながります。この記事では、Nginx をリバースプロキシにした1台構成の例で、環境の分け方、データの扱い、確認と切り替え、切り戻しまでを説明します。

Blue-Green とリリースディレクトリ方式の違い

ゼロダウンタイムデプロイには、1つの環境の中でリリースディレクトリのリンクを切り替える方法もあります(ShipIt や Deployer の方式)。こちらはファイルの入れ替えが一瞬で済むことが目的で、PHP やミドルウェアは共通です。

Blue-Green は環境そのものを丸ごと2つ持ちます。PHP のバージョンアップ、PHP 拡張の追加、Web サーバー設定の変更など、ファイル以外の変更も待機側で事前に試せる点が大きな違いです。その代わり、サーバー資源は2倍近く必要になり、状態(データ)を持つ部分の設計が難しくなります。テーマやプラグインの更新だけならリリースディレクトリ方式で十分なことが多く、ミドルウェアごと更新したい場面で Blue-Green が向いています。

構成の全体像

ここでは次の構成を例にします。

  • 前段の Nginx(443番ポート)が、blue か green のどちらかへリクエストを転送する
  • Blue は 127.0.0.1:8081、Green は 127.0.0.1:8082 で待ち受ける、それぞれ独立した WordPress 環境(別のドキュメントルートと PHP-FPM プール、または Docker Compose のスタック)
  • データベースとアップロードファイルは両環境から共有する

複数台のサーバーで組む場合は、前段を HAProxy やクラウドのロードバランサーに置き換えても考え方は同じです。

状態を持つ部分の決め方

Blue-Green で一番考えるべきなのは、コードではなくデータです。WordPress では次の4つを整理します。

データベース

選択肢は大きく2つです。

  1. 両環境で同じデータベースを共有する: 投稿やコメント、注文が切り替えで失われません。そのかわり、待機側の新しいコードが本番稼働中の古いコードと同じテーブルを使うため、テーブル構造を変える更新には注意が必要です。列やテーブルを追加する変更を先に入れ、新旧どちらのコードでも動く状態を保ち、古い列の削除は切り替え後の別リリースで行う「拡張してから縮小する」進め方をとります。
  2. 待機側にデータベースを複製する: 大型プラグインのメジャー更新のように、テーブル構造が大きく変わる場合はこちらが安全です。ただし、複製してから切り替えるまでに本番側で書き込まれたデータは待機側にありません。その間は投稿や会員登録を止める「更新停止時間」を設けるか、差分を移す手順が必要になり、厳密にはダウンタイムゼロではなくなります。

多くのサイトでは、普段は共有、構造変更を伴う大きな更新のときだけ複製、と使い分けるのが現実的です。WordPress コアの更新でもデータベースの更新処理が走ることがあるため、更新内容はリリースノートで確認してください。

アップロードファイル

wp-content/uploads は両環境で同じ場所を参照させます。1台構成なら同じディレクトリをシンボリックリンクやバインドマウントで共有し、複数台なら NFS などの共有ストレージか、S3 互換ストレージへのオフロードを検討します。共有しないと、切り替え後に直前にアップロードした画像が見つからなくなります。

WP-Cron とバックグラウンド処理

WP-Cron はページへのアクセスをきっかけに動くため、待機側に確認のアクセスをすると、待機側でも予約投稿やメール送信が実行されることがあります。両環境の wp-config.php に define( 'DISABLE_WP_CRON', true ); を入れ、システムの cron から本番側だけで WP-Cron を実行する形にすると、二重実行を防げます。

オブジェクトキャッシュとセッション

Redis などのオブジェクトキャッシュを共有している場合、新旧のコードが同じキャッシュを読み書きします。キャッシュの中身の形式が変わる更新では、切り替え直後にキャッシュを消すか、環境ごとにキーの接頭辞を分けておくと、古いデータによる不具合を避けられます。

Nginx で振り分け先を切り替える

前段の Nginx では、2つの upstream を定義し、map で振り分け先を決めます。確認用の Cookie を持つアクセスだけを待機側へ送れるようにしておくと、本番と同じドメインのまま待機側を確認できます。

# /etc/nginx/conf.d/bluegreen.conf
upstream wp_blue  { server 127.0.0.1:8081; }
upstream wp_green { server 127.0.0.1:8082; }

map $cookie_bg_preview $wp_backend {
    include /etc/nginx/bluegreen/live.map;   # 本番と確認用の振り分け先
}

server {
    listen 443 ssl;
    http2 on;
    server_name www.example.com;
    # ssl_certificate などは省略

    location / {
        proxy_pass http://$wp_backend;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

live.map は環境ごとに2つ用意し、シンボリックリンクで切り替えます。

# /etc/nginx/bluegreen/live-blue.map(Blue が本番、確認用 Cookie だけ Green へ)
default  wp_blue;
preview  wp_green;

# /etc/nginx/bluegreen/live-green.map(Green が本番、確認用 Cookie だけ Blue へ)
default  wp_green;
preview  wp_blue;

http2 on; は Nginx 1.25.1 以降の書き方で(2026年10月現在)、それより古い版では listen 443 ssl http2; と書きます。proxy_pass に変数を使う場合、値が定義済みの upstream 名と一致すれば、そのグループへ転送されます。

バックエンド側の WordPress は前段からの HTTP 接続を受けるため、HTTPS で表示されていることを伝える必要があります。前段の Nginx からしか接続できない構成にしたうえで、wp-config.php に次を入れます。

// 信頼できるリバースプロキシ経由のときだけ HTTPS とみなす
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
    $_SERVER['HTTPS'] = 'on';
}

これを入れないと、管理画面へのリダイレクトが繰り返される、CSS が http で読み込まれる、といった症状が出ます。

デプロイから切り替えまでの手順

現在 Blue が本番だとして、Green に新しい版を入れる流れは次のとおりです。作業前にデータベースのバックアップを取り、手順はステージングで一度通しておきます。

  1. Green に新しいコード、PHP やミドルウェアの変更を反映する
  2. Green 側で動作確認する。ブラウザで bg_preview=preview の Cookie を付けて本番ドメインにアクセスすると Green が表示される
  3. 機械的な確認も行う
# 待機側に直接アクセスしてステータスを確認(Host ヘッダーを本番ドメインにする)
curl -sS -o /dev/null -w '%{http_code}\n' -H 'Host: www.example.com' http://127.0.0.1:8082/
curl -sS -o /dev/null -w '%{http_code}\n' -H 'Host: www.example.com' http://127.0.0.1:8082/wp-login.php
  1. 問題がなければ振り分けを切り替える
cd /etc/nginx/bluegreen
sudo ln -sfn live-green.map live.map
sudo nginx -t && sudo systemctl reload nginx

Nginx の reload は、新しい設定のワーカーを起動し、古いワーカーは処理中のリクエストを終えてから停止します。そのため接続を切らずに振り分け先を変えられます。nginx -t で構文エラーが見つかった場合は reload されないので、本番が止まることはありません。

  1. 切り替え後、エラーログとアクセスログを数分間見て、5xx が増えていないか確認する

切り戻しと後片付け

問題が見つかったら、リンクを live-blue.map に戻して reload すれば、元の環境にすぐ戻せます。Blue はそのまま動いているので、復旧は数秒で終わります。

ただし、戻るのはアプリケーションの環境だけです。データベースを共有している場合、新しい版が書き込んだデータや変更したテーブル構造は残ります。プラグインがテーブル構造を変える更新を含む場合は、切り戻したときに古いコードで動くかを事前に確認するか、データベースを複製する方式を選んでください。

切り替えが安定したら、古い側(この例では Blue)は次回のデプロイ先になります。しばらくは切り戻し用に残し、次の更新時に新しい版で上書きします。

まとめ

  • Blue-Green は環境を2つ持ち、待機側で確認してから振り分けを切り替える方式で、PHP やミドルウェアの更新も事前に試せます。
  • WordPress ではデータベース、アップロード、WP-Cron、オブジェクトキャッシュの扱いを先に決めます。データベースは普段は共有し、構造が大きく変わる更新だけ複製するのが現実的です。
  • Nginx の upstream と map を使えば、Cookie で待機側を確認し、リンクの差し替えと reload で切り替えられます。
  • 切り戻しは速い一方、データベースの変更は戻りません。バックアップと手順の事前確認を欠かさないでください。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲