Eyes, JAPAN Blog > wp-env の環境に既存のデータベースを同期する

wp-env の環境に既存のデータベースを同期する

ishii

WordPressのローカル開発にはwp-envを利用しています。
wp-envの公式ドキュメントではSQLをマッピングして読み込む方法が紹介されていますが、実際の現場では ローカル ⇄ 本番サーバ の双方向で push / pull を行いたいことが多いため、wp-env環境でデータベースの相互同期を行うスクリプトを作成しました。

wp-envとは?
wp-envは、WordPress の公式が提供するローカル開発ツールです。
公式ドキュメント:Get started with wp-env – Block Editor Handbook | Developer.WordPress.org
Node.js と Docker をベースに動作し、簡単なコマンドで WordPress の環境(PHP・MySQL・Apache)をローカルに構築できます。

開発環境といえば Local by Flywheel も定番ですが、チーム開発においてwp-envは.wp-env.jsonに開発環境の構成を定義でき、チーム間で統一可能なこと、誰がどのPCで立ち上げても同じWordPress環境を再現できる点が大きな利点です。

前提条件

  1. 動作確認バージョン

    • Node v22.14.0
    • @wordpress/env: 10.24.0
    • WP-CLI: v2.12.0(※wp-envインストール時にインストールされます)
    • PHP: v8.3.23
    • wordpress: v6.8.2
  2. 本番サイト
    本番サーバにWP-CLIが含まれていることを前提としています。標準機能として提供されていないサーバを利用している場合は事前にインストールしてください。
  3. wp-envの設定
    wp-envをローカルにインストールする際に以下の設定をしています。

    引用:ローカルパッケージとしてのインストール
    このプロジェクトではグローバルインストールや npx を使いたくなければ、package.json を変更し、npm scripts にコマンドを追加してください。

    "scripts": {
            "wp-env": "wp-env"
          }

    この方法で wp-env をインストールした場合、すべての wp-env コマンドの前に npm run を追加してください。例:npm run wp-env start

    ここで紹介するスクリプトでもこのコマンドを利用しています。

最終的なディレクトリ構成(関連ファイルのみ)

project/
└─ env.sh // 本番サイト接続情報
└─ ssh/ // SSH key 格納場所
└─ sql/ // database格納場所
    ├─ local-db.sql
    ├─ remote-db.sql
    └─ backup-remote.sql
└─ sync/ // 同期用スクリプト
    ├─ setup-ssh.sh
    ├─ db-pull.sh
    ├─ media-pull.sh
    ├─ db-push.sh
    └─ media-push.sh
└─ wordpress/ // WordPress資材
    ├─ wp-config.php
    └─ wp-content
└─ .gitnone
└─ .wp-env.json // wp-envをインストールした時に生成される設定ファイル

①本番サイト→ローカルにインポート

※以下のコードはファイル構成によってスクリプトを書き換える必要があります。

インポートの準備

リポジトリサイズの肥大化を避けるため、.gitnoneにはメディアファイル、インポートしたsql、そしてSSH Keyを追加してください。

# .gitnone
# wp-env
wordpress/wp-content/uploads/*
sql/*.sql

# password
ssh/*

本番サイトの接続情報を登録する

wp-envプロジェクト直下にenv.shファイルを作成します。

# Macの場合
touch env.sh 

env.shファイルに本番サイトの接続情報を書きます。

# env.sh
# 本番サイトのURL
REMOTE_URL=https://xxx.jp/wordpress
# 本番サイトのWordPressディレクトリのパス
REMOTE_PATH=/home/www/wordpress
# 本番サイトのSSHホスト名
REMOTE_HOST=xxx.jp
# 本番サイトのSSHユーザー名
REMOTE_USER=xxx
# 本番サイトの database の table_prefix
REMOTE_DB_PREFIX=wp_xxx

# LocalWordPressディレクトリのパス
LOCAL_WP_PATH=wordpress
# LocalPort
LOCAL_SERVER_PORT=8888

# sql
LOCAL_SQL_DIR=sql
LOCAL_SQL_PATH=${LOCAL_SQL_DIR}/local-db.sql
REMOTE_SQL_PATH=${LOCAL_SQL_DIR}/remote-db.sql
BACKUP_SQL_PATH=${LOCAL_SQL_DIR}/backup-remote.sql

# SSH Key
SSH_DIR=ssh
SSH_KEY=id_rsa
SSH_KEY_PATH=${SSH_DIR}/${SSH_KEY}
REMOTE_SSH_PATH=/home/xxx

初回のみSSHキーを登録

データベースインポートを実行するたびに本番サーバーの接続パスワードを入力する手間を省くため、SSHキーベース認証を設定します。
プロジェクトに空のディレクトリsyncを作成し、その中にsetup-ssh.shを作成します。

# Macの場合
mkdir sync
touch sync/setup-ssh.sh

setup-ssh.shに以下を貼り付けてください。ここで先ほど作成したenv.shの内容を使用しています。

# setup-ssh.sh
#!/bin/bash

source ./env.sh

# 🔐 If the key does not exist, generate it.
if [ ! -f "$SSH_KEY_PATH" ]; then
  echo "== 🔑 Generate SSH key =="
  mkdir -p "$SSH_DIR"
  ssh-keygen -t rsa -b 4096 -f "$SSH_KEY_PATH" -N ""
else
  echo "== 🔍 SSH key already exists: $SSH_KEY_PATH =="
fi

# 🛫 Transfer the public key to the remote and append it to authorized_keys
echo "== 📤 Register the public key to the remote =="
PUBKEY=$(cat "${SSH_KEY_PATH}.pub")

ssh "${REMOTE_USER}@${REMOTE_HOST}" "mkdir -p $REMOTE_SSH_PATH/.ssh && touch $REMOTE_SSH_PATH/.ssh/authorized_keys && grep -qxF '$PUBKEY' $REMOTE_SSH_PATH/.ssh/authorized_keys || echo '$PUBKEY' >> $REMOTE_SSH_PATH/.ssh/authorized_keys $REMOTE_SSH_PATH/.ssh/authorized_keys"

ssh -i "$SSH_KEY_PATH" "${REMOTE_USER}@${REMOTE_HOST}" "echo 'SSH Success 🎉'"

スクリプトを実行すると、ローカルでSSHキーを生成しリモートサーバーに自動登録されます。
※このプロセス中に本番サーバーのパスワード(FTPログインパスワード)の入力を求められます。パスワード入力時はターミナル画面に何も表示されませんが正常な動作です。

sync/setup-ssh.sh
# password入力 → SSH Success 🎉

次回以降はパスワードなしで同期可能になります。

.wp-env.jsonの mapping にインストールしたデータベースを共有するための記述を追加します。

# .wp-env.json
"mappings": {
  "sql": "./sql"
  ".htaccess": ".htaccess"
}

データベースインポート

syncの中にdb-pull.shを作成します。

# Macの場合
touch sync/db-pull.sh

db-pull.shに以下を貼り付けてください。

# sync/db-pull.sh
#!/bin/bash

source ./env.sh

# Export local backup
npm run wp-env run cli wp db export $LOCAL_SQL_PATH

# -------------------------------------------
# Database pull
# -------------------------------------------

echo "== 📥 Export DB remotely and save locally =="
ssh -i $SSH_KEY_PATH ${REMOTE_USER}@${REMOTE_HOST} "wp --path=$REMOTE_PATH db export - --add-drop-table" > $REMOTE_SQL_PATH

echo "== 🛠 Import DB to wp-env =="
npm run wp-env run cli wp db import $REMOTE_SQL_PATH

echo "== 🛠 Change table_prefix in wp-config.php =="
npm run wp-env run cli wp config set table_prefix $REMOTE_DB_PREFIX --type=variable

echo "== 🔍 search-replace URL =="
npm run wp-env run cli wp search-replace "$REMOTE_URL" "<http://localhost>:${LOCAL_SERVER_PORT}/" \\
  --skip-columns=guid --all-tables --precise

実行内容

  1. 本番サイトからdatabaseをエクスポート
  2. ローカルのwp-envにインポート
  3. 接頭辞を本番サイトのものに変更
  4. URLをローカルに書き換え

スクリプトを実行するとローカルに本番サイトのデータベースがインポートされます。

sync/db-pull.sh
# Success: Imported './sql/local-db.sql'
# Success: Made 380 replacements.

メディアのインポート(任意)

※メディアのファイルサイズが大きい場合は時間がかかるので飛ばしても構いません。
syncの中にmedia-pull.shを作成します。

# Macの場合
touch sync/media-pull.sh

media-pull.shに以下を貼り付けてください。

#!/bin/bash

source ./env.sh

echo "== 📦 Import media (uploads folder)  =="
scp -i "$SSH_KEY_PATH" -r ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/wp-content/uploads/* \\
  ${LOCAL_WP_PATH}/wp-content/uploads/

echo "== ✅ Done =="

クリプトを実行してください。初回はファイルサイズによって数分かかる場合があります。

sync/media-pull.sh

確認とログイン

ここまでで npm run wp-env start でローカル環境を立ち上げると、本番サイトが再現されている状態になります。
なお、管理画面にアクセスする際のユーザー名・パスワードは本番サイトと同じものを入力してください。

  • 管理画面:http://localhost:8888/wp-admin/
  • ユーザー名/パスワード:本番サイトと同じ

②ローカル→本番サイトにプッシュ

エクスポートの準備

syncの中にdb-push.shを作成します。

# Macの場合
touch sync/db-push.sh

db-push.shに以下を貼り付けてください。
※間違ってプッシュしてしまった時に戻せるように sql/backup-remote.sql に本番サイト側のsqlを保存しています。

#!/bin/bash

source ./env.sh

mkdir -p "${LOCAL_SQL_DIR}"

# 本番サイトのsqlをバックアップする
ssh -i $SSH_KEY_PATH ${REMOTE_USER}@${REMOTE_HOST} "wp --path=$REMOTE_PATH db export - --add-drop-table" > $BACKUP_SQL_PATH

# -------------------------------------------
# Database push
# -------------------------------------------

echo "== 🧠 Exporting local DB =="
# WordPress のユーザーパスワードは ***.user_pass にハッシュで保存されています($P$ などで始まる値)。
# MariaDB (wp-env) から MySQL (remote) にインポートした際に、このハッシュ値が上書きされてしますのでエクスポートをスキップします。
npm run wp-env run cli -- wp db export ${LOCAL_SQL_PATH} --exclude_tables=${REMOTE_DB_PREFIX}users

echo "== 🔍 Replace unsupported collation with a compatible one =="
# MariaDB 11.8.2 (wp-env) → MySQL 8.0 (remote) なので
# utf8mb3_uca1400_ai_ci → utf8mb4_general_ci に変換
if [[ "$OSTYPE" == "darwin"* ]]; then
  sed -i '' 's/utf8mb4_uca1400_ai_ci/utf8mb4_unicode_ci/g' "${LOCAL_SQL_PATH}"
  sed -i '' 's/utf8mb3_uca1400_ai_ci/utf8mb3_unicode_ci/g' "${LOCAL_SQL_PATH}"
  sed -i '' 's/CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci/CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci/g' "${LOCAL_SQL_PATH}"
  sed -i '' 's/CHARSET=utf8mb3 COLLATE=utf8mb3_uca1400_ai_ci/CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci/g' "${LOCAL_SQL_PATH}"
else
  sed -i 's/utf8mb4_uca1400_ai_ci/utf8mb4_unicode_ci/g' "${LOCAL_SQL_PATH}"
  sed -i 's/utf8mb3_uca1400_ai_ci/utf8mb3_unicode_ci/g' "${LOCAL_SQL_PATH}"
  sed -i 's/CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci/CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci/g' "${LOCAL_SQL_PATH}"
  sed -i 's/CHARSET=utf8mb3 COLLATE=utf8mb3_uca1400_ai_ci/CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci/g' "${LOCAL_SQL_PATH}"
fi

echo "== 📤 Copying DB dump to remote server =="
ssh ${REMOTE_USER}@${REMOTE_HOST} "mkdir -p ${REMOTE_PATH}/$(dirname ${LOCAL_SQL_PATH})"
scp ${LOCAL_SQL_PATH} ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/${LOCAL_SQL_PATH}

echo "== 🛠 Importing dump into remote DB =="
ssh ${REMOTE_USER}@${REMOTE_HOST} "
  cd ${REMOTE_PATH} && \\
  wp db import ${LOCAL_SQL_PATH} --allow-root && \\
  wp search-replace '<http://localhost>:${LOCAL_SERVER_PORT}' '${REMOTE_URL}' --skip-columns=guid --all-tables --allow-root && \\
  rm -f ${LOCAL_SQL_PATH}
"

echo "== ✅ Done =="

クリプトを実行してください。

sync/db-push.sh

メディアプッシュ

メディアをローカルにインポートしている場合は、syncの中にmedia-push.shを作成します。

# Macの場合
touch sync/media-push.sh

media-push.shに以下を貼り付けてください。差分だけアップロードするようにしています。

#!/bin/bash

source ./env.sh

echo "== 📤 Upload Media (uploads folder)  =="
# 差分だけアップロード
rsync -avz \\
  -e "ssh -i $SSH_KEY_PATH" ${LOCAL_WP_PATH}/wp-content/uploads/ \\
  ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/wp-content/uploads/

echo "== ✅ Done =="

クリプトを実行してください。

sync/media-push.sh

本番サイトを開いてプッシュされていることを確認してください。

スクリプト実行時に zsh: permission denied xxx.sh というエラーが表示される場合は、ファイルに実行権限を付与してください: chmod +x sync/media-push.sh

まとめ

現状の本番サーバ環境の条件に合った同期ツールがなかなか見つからなかったため今回のスクリプトを作成しました。
初回の同期設定を済ませておくと、次回からはコマンド一つでローカルと本番のデータベースを同期できるようになります。
wp-envを使ったWordPress開発をよりスムーズに進めたい方は、ぜひ今回の方法を取り入れてみてください。

Comments are closed.