WordPressでステージング環境を利用して開発っぽい開発を志向する
今回のテーマは「WordPressでステージング環境を利用して開発っぽい開発を志向する」という長いタイトルで、上のh1
が折り返されてしまいますが、 所謂「WEB開発の三環境」を、WordPressをCMSとしてフィーチャーしたサイトにも当て嵌めて、開発効率を向上させよう!といった趣旨です。
私たちの部署ではプロダクションレベルでWordPressを利用することは正直あまりないのですが、いざ「やろう!」となった時、進行管理で困ったことが起こります。
例えば、、、
- 自作プラグインのテスト環境が欲しい
- Postをプレビューできる環境が欲しい
- テンプレートの変更箇所を事前にブラウザでチェックしたい
等々。本番とは別の環境(サーバ)で確認したい事が多々発生します。
ステージング環境とは?
ですので、公開用の本番環境とは別にサーバを用意してテスト/プレビューするのですが、そういうのを開発の現場では「ステージング環境」と言います。
- 開発サーバ = 開発者用テスト環境
- ステージングサーバ = 動作確認環境
- プロダクションサーバ = 本番環境
業務で制作するWEBアプリケーションの場合だと、複数人で開発を行うことが多いのですが、 それぞれの開発者が「開発サーバ」でコーディングしたものをGitでマージして、「ステージングサーバ」に上げ、動作確認を取り、問題なければ、「プロダクションサーバ」にデプロイ。
というフローになります。
(「開発環境」の構築と運用については別の機会に・・・)
さて、ステージング環境でテスト/プレビュー済みのファイル/データを「良いね~本番に公開しましょう」となった時、 本番環境に合わせてwp-config.php
を書き換えてからデプロイしたり、 一旦、リネームして、デプロイ後、元に戻したり、 はたまたデプロイした後、ターミナルで直接編集したり・・・
そういった方法だど、アップ/デプロイミスも起こりやすく、そもそもWEBサイトのアップデートでは、ダウンタイムが数秒でも発生するのは避けたい~
ということで、ステージング環境のファイル/データをそのまま本番環境にデプロイしても、ちゃんと動作するようにする。というのが理想なのですが、 開発/ステージング環境と本番環境では当然ドメイン(URL)が違いますし、データベース情報も同じではない事が大半ですので、そこは何らかの方法で切り分けなければなりません。
環境変数
そこで、サーバ毎に「環境変数」というのを定義して、その違いで各情報の読み込みを条件分岐させます。
環境変数はApacheやNginxの設定ファイル(httpd.conf
,nginx.conf
等)でも、php.iniでも、.htaccessでも定義できます。
Apacheの場合だと、xxx.conf
に、
<VirtualHost *:80> ServerName staging.example.com DocumentRoot /var/www/vhosts/staging.example.com/httpdocs <Directory "/var/www/vhosts/staging.example.com/httpdocs"> Options FollowSymLinks allowoverride all Require all granted </Directory> SetEnv WP_ENV staging </VirtualHost>
等と、SetEnv
部分を追記します。
Apacheを再起動すると定義が反映されますので、phpinfo()
で確認してみましょう。
下の方のPHP Variables
欄に$_SERVER['WP_ENV']
という欄があれば設定成功です。
ということは、PHPで呼び出す場合は、
$_SERVER['WP_ENV'];
でOKです。
但し、レンタルサーバとかだと無理なので、パブリックなサーバの場合だと、php.iniか.htaccessに頼らざるを得ないと思いますが、その場合でも、
~ SetEnv WP_ENV staging ~
と追記しておけば良いはずです(こちらは検証してません)
WPの便利な定数
上記の方法で、データベースに関する情報を環境によって分岐させることが可能だとご理解いただけると思いますが、 ステージング環境と本番環境では当然、ドメイン(URL)が違いますので、結局、データベースのwp_options
テーブルに設定されているsiteurl
とhome
を書き換えなければ、閲覧もママなりません。
しかし、この2つの項目、wp-conf.php
上で定数として定義が可能です。
define('WP_HOME', 'https://example.com/'); //(クライアントの)TOP define('WP_SITEURL', 'https://example.com/wp/'); //インストール先
と定義すると、データベースに設定されたsiteurl
とhome
よりも優先して読み込んでくれます。
分岐方法
では、実際にwp-conf.php
にどう書けばよいか~の例を以下に。
<?php ~ if (isset($_SERVER['WP_ENV']) && $_SERVER['WP_ENV'] == 'staging') { // ステージング環境用の設定 define('WP_HOME', 'https://staging.example.com'); // (ステージング環境の)クライアントのTOP define('WP_SITEURL', 'https://staging.example.com/wp'); // (ステージング環境の)インストール先 define('DB_NAME', 'staging_rdb'); // (ステージング環境の)WordPress のためのデータベース名 define('DB_USER', 'staging_rdb_user'); // (ステージング環境の)MySQL データベースのユーザー名 define('DB_PASSWORD', 'xxxxxxxx'); // (ステージング環境の)MySQL データベースのパスワード define('DB_HOST', 'localhost'); // (ステージング環境の)MySQL のホスト名 } else { // 本番環境用の設定 define('WP_HOME', 'https://www.example.com'); // (本番環境の)クライアントのTOP define('WP_SITEURL', 'https://www.example.com/wp'); // (本番環境の)インストール先 define('DB_NAME', 'propduction_rdb'); // (本番環境の)WordPress のためのデータベース名 define('DB_USER', 'propduction_rdb_user'); // (本番環境の)MySQL データベースのユーザー名 define('DB_PASSWORD', 'xxxxxxxx'); // (本番環境の)MySQL データベースのパスワード define('DB_HOST', 'localhost'); // (本番環境の)MySQL のホスト名 } ~
環境変数を(最低限)ステージング環境だけ設定しておけば、上記のような簡単な条件分岐で環境の切り分けが可能になります。
メンテナンス性
ところで、WordPressサイトのメンテナンスにコマンドラインツールWP-CLI
を利用する場合も多いと思います。
このツールはコマンドラインPHPで動作させてますので、環境変数で条件分岐させたwp-config.php
では問題が発生します。 例えば、プラグインのアップデートを行おうと、
$ wp plugin update --all
としても動作しません。
なぜなら先程設定した環境変数WP_ENV
は、どの方法を採ったとしてもApache経由でアクセスされない限りは有効になりませんので、コマンドラインでは読み込まれません。
コマンドラインツールを使うということは、ターミナル等を使って何らかのユーザーでログインしているということですので、~/.bashrc
か~/.bash_profile
で環境変数を定義すれば良いのですが、 その方法だとユーザーに依存してしまいますので妥当な方法ではないでしょう。
サーバ全体で(ユーザーが誰であれ)環境変数を有効にする方法もありますが、バーチャルホストで「複数プロジェクトの各種環境が存在する」サーバを利用するケースもあるかと思いますので、オススメできません。
対処方法は簡単で、コマンド実行時に環境変数を指定してあげれば良いだけです。 先程の場合だと、
$ export WP_ENV=testing; wp plugin update --all
こうすれば、環境変数WP_ENV
の値がtesting
であるとして、WP_CLI
が実行されます。
デプロイ
これで、全ての環境で全てのファイルを共通にする事ができました。 (WordPressの場合だと、upload
ディレクトリをリポジトリに含めるか含めないか~で議論になりそうでは有りますけど・・・)
デプロイに関して、私たちは「ステージング環境」から「本番環境」へのデプロイは、rsync
を利用して行ってますが、git pull
でもftp
でもお好みでどうぞ。
肝心のデータベースは?
このPostのはじめに、
Postをプレビューできる環境が欲しい
って、書いているのだから、DBの同期方法についても言及すべき~
というツッコミもあるかもしれません。
DBの同期、準同期、レプリケーションについては、それだけで1冊本が必要なくらいのカテゴリですので、
「WordPressでPostのプレビュー用途に最適なDBの同期方法」
といったようなテーマでまたの機会にPostしたいと思います~(汗)
※ 続編Postしました! WordpressでPostのプレビュー用途に最適なDBの同期方法