RHEL/AlmaLinux環境でのWordPressバックアップ問題 – MySQL 9.1アップデート後の対処法

バックアップ自動化の罠 – MySQL 9.1アップデートによる問題と解決方法

WordPressのバックアップ自動化は、多くの運用者にとって重要なタスクです。特にRHEL系(RHEL/AlmaLinux)環境でのDocker運用において、一見問題なく動作していたバックアップスクリプトが、MySQLの9.1へのアップデート後に突然機能しなくなるという事態に遭遇しました。

この記事では、この問題の解決方法と、なぜこのような問題が発生したのかを詳しく解説していきます。

目次

環境構成

本記事で使用している環境は以下の通りです:

・OS: AlmaLinux(RHEL互換)
・アーキテクチャ: ARM64/v8
・Docker & Docker Compose
・WordPress(最新版)
・MySQL 9.1

必要なファイル構成は以下になります:

wordpress-docker/
├── docker-compose.yml(コンテナ構成定義)
├── Dockerfile(WordPressコンテナのカスタマイズ)
├── entrypoint.sh(起動時の初期設定スクリプト)
├── setup.sh(環境セットアップスクリプト)
├── .env(環境変数設定)
├── php.ini(PHP設定ファイル)
└── backup/(バックアップ保存ディレクトリ)

問題の発生

ある日、通常のシステムアップデートの一環としてMySQLが9.1にアップデートされました。その後、毎日実行されているはずのバックアップが取得できなくなっていることに気がつきました。

予期せぬエラーとその対処

システムを運用していく中で、以下のようなエラーメッセージに遭遇しました:

template parsing error: template: :1:8: executing "" at <.State.Health.Status>: map has no entry for key "Health"

このエラーは、Dockerコンテナのヘルスチェック機能に関連する問題です。興味深いことに、このエラーは断続的に発生し、時として自然に解消されることもありました。

問題の原因と対策

このような予期せぬ動作の変化は、Docker環境では珍しくありません。主な要因として以下が考えられます:

・Dockerデーモンのキャッシュのクリア
・システムの再起動によるステータスのリセット
・Dockerの自動アップデート
・コンテナの起動タイミングや依存関係の問題

解決策:docker-compose.ymlの改善

この問題に対処するため、docker-compose.ymlファイルにヘルスチェックの設定を追加し、より堅牢な構成に修正しました:

WordPressコンテナの設定:

healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

データベースコンテナの設定:

healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

セットアップスクリプトの改善

また、setup.shスクリプトも、より確実にコンテナの状態を確認できるように改良しました:

while true; do
status=$(docker inspect wordpress 2>/dev/null | jq -r '.[0].State.Status')
if [ "$status" = "running" ]; then
if docker exec wordpress curl -s -f http://localhost:80 >/dev/null 2>&1; then
echo "WordPressコンテナが正常に動作しています"
break
fi
fi
echo "WordPressコンテナの起動を待っています..."
sleep 5
done

運用上の推奨事項

今回の経験から、以下の運用方針を推奨します:

  1. ログの定期的な保存
docker compose logs > docker_logs_$(date +%Y%m%d).txt
  1. システム状態の定期確認
docker system events --since 30m  # 過去30分のイベントを確認
  1. 重要な操作前のバックアップ取得
docker exec wordpress-db mysqldump -u root -p wordpress > backup_$(date +%Y%m%d).sql

このように設定を改善することで、システムの安定性と信頼性が向上しました。

本質的な問題:データベースバックアップの失敗

システムの安定性が向上した一方で、より深刻な問題に直面しています。データベースのバックアップが取得できないのです。

一般的なバックアップコマンドを実行すると:

docker exec wordpress-db mysqldump -u root -p dbin > backup_$(date +%Y%m%d).sql

次のようなエラーが発生します:

Enter password: 
mysqldump: Got error: 1045: Access denied for user 'root'@'localhost' (using password: NO) when trying to connect

このエラーは非常に深刻な問題です。なぜなら:

・日次バックアップが実行できない
・障害発生時のリカバリーが困難
・システムの安全性が確保できない

なぜこの問題が発生したのか?

この問題は、MySQL 9.1へのアップデート後に発生しました。従来は正常に動作していたバックアップ処理が、アップデート後に突如として失敗するようになったのです。

解決への道のり

1. 最初の試み:通常のバックアップコマンド

まず、一般的なバックアップ方法を試みましたが、認証エラーが発生しました:

docker exec wordpress-db mysqldump -u root -p dbin > backup_$(date +%Y%m%d).sql
Enter password: 
mysqldump: Got error: 1045: Access denied for user 'root'@'localhost' (using password: NO) when trying to connect

2. 一時的な回避策の検討

次に、以下のような対応を試みましたが、いずれも成功しませんでした:

  • パスワードを直接指定する方法
  • 異なるユーザーでのアクセス
  • コンテナ内でのバックアップ実行
docker exec -it wordpress-db bash
mysqldump -u root -p dbin > dbin_backup.sql
docker exec wordpress-db mysqldump -u root -p dbin > dbin_backup.sql

コンテナ内であろうが、外であろうが以下のエラーでエクスポートできません。

mysqldump: Got error: 1045: Access denied for user ‘root’@’localhost’ (using password: YES) when trying to connect

エクスポートすることに専念していたが、そもそもログインができるかどうか確認するとそれすら不可になっていました。

3. 解決策:一時的な環境を使用したバックアップ方法

最終的に、以下の手順で問題を解決することができました:

  1. 一時的なデータディレクトリの準備:
# 一時ディレクトリを作成
mkdir -p temp_mysql_data temp_run_mysqld

# データをコピー
sudo cp -r db_data/* temp_mysql_data/
  1. バックアップの実行:
docker run --rm --platform linux/arm64/v8 \
  -v $(pwd)/temp_mysql_data:/var/lib/mysql \
  -v $(pwd)/temp_run_mysqld:/var/run/mysqld \
  -v $(pwd)/backup:/backup \
  mysql:9.1 \
  bash -c 'docker-entrypoint.sh mysqld --skip-grant-tables --skip-networking & sleep 30 && mysqldump --no-tablespaces --skip-add-drop-table --all-databases > /backup/full_backup_$(date +%Y%m%d_%H%M%S).sql && sleep 5'
  1. 後片付け:
# 一時ディレクトリの削除
sudo rm -rf temp_mysql_data temp_run_mysqld

なぜこの方法が有効なのか?

この解決策が機能する理由は以下の通りです:

  1. 認証をスキップすることで、MySQL 9.1の厳格な認証要件を回避
  2. ネットワークアクセスを無効化し、セキュリティを確保
  3. 一時的な環境を使用することで、本番環境に影響を与えない

解決策の詳細説明

先ほど示したバックアップ方法について、詳しく解説します。

コマンドの構成要素

docker run --rm --platform linux/arm64/v8 \
  -v $(pwd)/temp_mysql_data:/var/lib/mysql \
  -v $(pwd)/temp_run_mysqld:/var/run/mysqld \
  -v $(pwd)/backup:/backup \
  mysql:9.1 \
  bash -c '...'

主要なオプションの説明:

  • --rm: コンテナ終了後に自動的に削除
  • --platform linux/arm64/v8: ARM64アーキテクチャを指定
  • -v オプション: 3つのボリュームマウントを設定
  1. データベースファイル用
  2. MySQLソケットファイル用
  3. バックアップ保存用

実行コマンドの解説

docker-entrypoint.sh mysqld --skip-grant-tables --skip-networking & sleep 30 && \
mysqldump --no-tablespaces --skip-add-drop-table --all-databases > \
/backup/full_backup_$(date +%Y%m%d_%H%M%S).sql && sleep 5

コマンドの各部分の役割:

  1. docker-entrypoint.sh mysqld
  • MySQLサーバーを初期化して起動
  • Docker公式イメージの標準的な起動方法
  1. --skip-grant-tables --skip-networking
  • 認証をスキップ
  • セキュリティのためネットワークアクセスを無効化
  1. sleep 30
  • MySQLサーバーの起動完了を待機
  • 実環境に応じて調整可能
  1. mysqldumpのオプション
  • --no-tablespaces: テーブルスペース情報を除外
  • --skip-add-drop-table: DROP TABLE文を生成しない
  • --all-databases: すべてのデータベースをバックアップ
  1. 出力ファイル名
  • タイムスタンプ付きで保存
  • 年月日_時分秒の形式で記録

使用上の注意点

  • 一時的なディレクトリの準備が必要
  • 実行には管理者権限(sudo)が必要な場合がある
  • バックアップ完了まで十分な待機時間を確保

より実践的な運用に向けた改良版ソリューション

これまで説明してきた一時的な環境でのバックアップ方法は、緊急時の対応として有効です。しかし、長期的な運用を考えると、より体系的なアプローチが必要になります。

1. docker-compose.ymlによる自動バックアップの実装

先ほどの構成に以下の改良を加えることで、より安定した運用が可能になります:

services:
  db:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  wpsql:
    depends_on:
      db:
        condition: service_healthy
    command: >
      /bin/bash -c "
      while ! mysqladmin ping -h \"$$MYSQL_HOST\" --silent; do
        sleep 1;
      done;
      while true; do
        echo 'Starting backup...';
        MYSQL_PWD=$$MYSQL_PASSWORD mysqldump -h $$MYSQL_HOST -u $$MYSQL_USER ${MYSQL_DATABASE} > /backup/${MYSQL_DATABASE}_backup.sql;
        echo 'Backup complete.';
        sleep 86400;
      done"

2. バックアップの二重化戦略

信頼性を高めるため、以下の2つの方法を併用することをお勧めします:

  1. wpsqlコンテナによる日次バックアップ
  • 自動的な定期バックアップ
  • システムの一部として統合管理
  • ヘルスチェックとの連携
  1. 一時環境を使用した手動バックアップ
  • 重要な変更前の確実なバックアップ
  • トラブル発生時の緊急バックアップ
  • 検証用データの取得

3. モニタリングと管理の強化

a. ヘルスチェックの監視

# コンテナの状態確認
docker ps
# ヘルスチェックの詳細確認
docker inspect wordpress-db | grep -A 10 Health

b. バックアップの成功確認

# バックアップファイルの確認
ls -l backup/
# 最新のバックアップファイルのサイズ確認
find backup/ -type f -name "*.sql" -mtime -1 -ls

c. ログの定期確認

# バックアップコンテナのログ確認
docker logs wpsql

4. リカバリー手順

a. バックアップからの復元

# データベースの復元
docker exec -i wordpress-db mysql -u root -p${MYSQL_ROOT_PASSWORD} < backup/[バックアップファイル名]

b. 障害時の切り替え手順

  1. コンテナの停止
  2. データディレクトリのバックアップ
  3. 新しいコンテナの起動
  4. データの復元

完成したボタン一発で起動するワードプレスのスクリプトのGithubページ

GitHub - superdoccimo/wpbk
Contribute to superdoccimo/wpbk development by creating an account on GitHub.

WordPressデータベースの移行時のトラブルシューティング実践

データベースの移行作業では、予期せぬ問題に直面することが多々あります。今回の作業では、複数の問題に遭遇し、それらを一つずつ解決していく過程で多くの学びがありました。

最初の課題:データベース接続エラー

発生した問題

WordPressサイトにアクセスすると以下のエラーが表示されました:

Error establishing a database connection

最初の試み

データベース名をdbinからdbfunに変更する際、以下の作業を行いました:

mysql> CREATE DATABASE dbfun;
mysql> USE dbfun;
mysql> SHOW TABLES;
Empty set (0.00 sec)

この時点で、新しいデータベースは作成されましたが、中身が空であることが判明しました。

2回目の課題:データの移行とパーマリンク

データベースの内容確認

mysql> USE dbin;
mysql> SHOW TABLES;
+--------------------------+
| Tables_in_dbin |
+--------------------------+
| wp_commentmeta |
| wp_comments |
| wp_links |
...(中略)...
| wp_users |
+--------------------------+
16 rows in set (0.00 sec)

元のデータベースにはデータが存在することを確認できました。

データベース移行作業の実施

データベースの内容を新しい環境にコピーするため、以下のコマンドを実行しました:

# データベースのバックアップを作成
docker exec wordpress-db mysqldump -u root -pTestPass dbin > dbin_backup.sql

# 新しいデータベースにリストア
docker exec -i wordpress-db mysql -u root -pTestPass dbfun < dbin_backup.sql

データ移行後の確認

sqlCopymysql> USE dbfun;
mysql> SHOW TABLES;
+--------------------------+
| Tables_in_dbfun          |
+--------------------------+
| wp_commentmeta           |
| wp_comments              |
| wp_links                 |
...(中略)...
| wp_users                 |
+--------------------------+
16 rows in set (0.01 sec)

新たな問題:パーマリンクの不具合

症状

  • トップページは表示される
  • 個別記事のURL(例:https://showa.fun/ubuntu-windows-share/)にアクセスすると404エラー

原因の特定

.htaccessファイルが存在しないことが判明:

docker exec wordpress cat /var/www/html/.htaccess
cat: /var/www/html/.htaccess: No such file or directory

.htaccessファイルの設定

ファイルの作成と設定

まず、必要な.htaccessファイルを作成しました:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

権限設定での注意点

ホストマシン(AlmaLinux)での権限設定時に、以下のエラーに遭遇しました:

sudo chown www-data:www-data .htaccess
chown: ユーザ指定が不正: 'www-data:www-data'

正しい権限設定方法

Dockerコンテナ内のApacheユーザーIDを確認:

docker exec wordpress id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)

この情報を基に、正しい権限を設定:

sudo chown 33:33 .htaccess
sudo chmod 644 .htaccess

データベース設定の確認

サイトURLの確認

mysql> SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl', 'home');
+-------------+-------------------+
| option_name | option_value |
+-------------+-------------------+
| home | https://showa.fun |
| siteurl | https://showa.fun |
+-------------+-------------------+

データベースの整合性確認

データの移行確認

両方のデータベースのレコード数を比較して、データが正しく移行されているか確認しました:

# dbinデータベースの確認
mysql> USE dbin;
mysql> SELECT COUNT(*) FROM wp_posts;
+----------+
| COUNT(*) |
+----------+
| 70 |
+----------+

# dbfunデータベースの確認
mysql> USE dbfun;
mysql> SELECT COUNT(*) FROM wp_posts;
+----------+
| COUNT(*) |
+----------+
| 70 |
+----------+

重要な設定の確認

テーマや基本設定が正しく移行されているか確認:

mysql> SELECT option_name, option_value 
FROM wp_options
WHERE option_name IN ('siteurl', 'home', 'template', 'stylesheet');
+-------------+-------------------+
| option_name | option_value |
+-------------+-------------------+
| home | https://showa.fun |
| siteurl | https://showa.fun |
| stylesheet | swell_child |
| template | swell |
+-------------+-------------------+

Apache設定の確認と調整

mod_rewriteの有効化

docker exec wordpress a2enmod rewrite
docker exec wordpress service apache2 reload

最終確認と動作テスト

サイトの動作確認

  1. トップページのアクセス確認
    • https://showa.fun へのアクセス
    • 記事一覧の表示確認
  2. 個別記事の確認
    • https://showa.fun/ubuntu-windows-share/ など、実際の記事URLへのアクセス
    • パーマリンク構造が正常に機能していることを確認
  3. 管理画面の確認
    • wp-adminへのログイン
    • データベース接続の安定性確認

データベースのクリーンアップ

古いデータベースの削除前の最終確認

# 新データベースの内容確認
mysql> USE dbfun;
mysql> SHOW TABLES;
mysql> SELECT COUNT(*) FROM wp_posts;

# 問題ないことを確認後、古いデータベースを削除
mysql> DROP DATABASE dbin;

重要な学びと注意点

  1. データベース移行時の確認事項
    • バックアップの重要性
    • データの整合性確認
    • ユーザー権限の適切な設定
  2. 環境依存の設定
    • コンテナ内のユーザーID(www-data: 33)の確認
    • ホストOSとコンテナの権限の違いへの対応
    • Apacheの設定調整
  3. トラブルシューティングのポイント
    • エラーメッセージの正確な理解
    • 段階的な問題解決
    • 各ステップでの動作確認

まとめ

MySQL 9.1環境でのWordPressバックアップには、以下の点が重要です:

  1. 適切なヘルスチェックの実装
  2. バックアップ方法の二重化
  3. 定期的なモニタリング
  4. 明確なリカバリー手順の整備

これらの要素を組み合わせることで、より信頼性の高いバックアップ体制を構築することができます。

タイトルとURLをコピーしました