WordPressのマイグレーション・引越し作業まとめ

Amazon Linuxが2020年にサポート終了となるため、Amazon LinuxからAmazon Linux 2へのお引越し作業を少しずつはじめました。

この機会にコンテナの構成を変えたり、PHPやMySQLのバージョンアップをしたりなど、よりモダンな基盤にアップデートすることに。

AWS以外でも作業の流れは同じと思いますので、似たような作業に遭遇することを考え、メモを残します。

バックアップ

WordPressのバックアップ

特に重要なのは__wp-content__配下にあるファイル群なので、基本的にはこれらを対象にバックアップをとります。

├── wp-content
│   ├── ewww
│   ├── languages
│   ├── plugins
│   ├── themes
│   ├── upgrade
│   └── uploads

しかし私は分けて管理するのが面倒だったため、全てのデータを丸ごとバックアップしています。

SSL/TLS証明書のバックアップ

新規に発行し直しても良いのですが、ローカルでテストもしたかったため、証明書類もバックアップをとりました。

MySQLデータのバックアップ

MySQLのデータのバックアップを行う前に、MySQL5.7から8へのバージョンアップしても問題ないかチェックします。

チェックするためにはMySQL Shellというツールをインストールします。このツールに__Upgrade Checker Utility__という関数がありまして、これを実行するとMySQLのアップグレードの際にエラーがないかとか、どこに注意してバージョンアップすれば良いのか分かり、事前に対策を打つことができます。

MySQL Shellのインストール

Upgrade Checker Utilityを使うには、MySQLを動かしているサーバーでMySQL Shellをインストールする必要があります。

↓インストール方法

https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-install.html

Upgrade Checker Utilityの実行

まずMySQL Shellを実行します。

mysqlsh --uri root@localhost

MySQLのShellに接続されるので、次にupgrade checkerを起動。

util.checkForServerUpgrade("root@localhost:3306")

↓こんな感じで出力結果が表示されます。

MySQL  localhost  JS > util.checkForServerUpgrade("root@localhost:3306")
Please provide the password for 'root@localhost:3306': ***************
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): y
The MySQL server at localhost:3306, version 5.7.19 - MySQL Community Server
(GPL), will now be checked for compatibility issues for upgrade to MySQL
8.0.15...

1) Usage of old temporal type
  No issues found

2) Usage of db objects with names conflicting with reserved keywords in 8.0
  ERROR: Cannot proceed because system tables used by Event Scheduler were found damaged at server start

  More information:
    https://dev.mysql.com/doc/refman/en/keywords.html

3) Usage of utf8mb3 charset
  Warning: The following objects use the utf8mb3 character set.
....

↓私の環境ではエラーが1つと警告が2つありました。

# エラーの内容
Cannot proceed because system tables used by Event Scheduler were found damaged at server start

このエラーについては、 mysql_upgrade を実行することで解決しました。

警告は下記のような内容でした。

# 警告その1
3) Usage of utf8mb3 charset
  Warning: The following objects use the utf8mb3 character set. It is
    recommended to convert them to use utf8mb4 instead, for improved Unicode
    support.
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html

  xxxxxx.wp_ewwwio_queue.gallery - column's default character set: utf8

# 警告その2
15) New default authentication plugin considerations
  Warning: The new default authentication plugin 'caching_sha2_password' offers
    more secure password hashing than previously used 'mysql_native_password'
    (and consequent improved client connection authentication). However, it also
    has compatibility implications that may affect existing MySQL installations.
    If your MySQL installation must serve pre-8.0 clients and you encounter
    compatibility issues after upgrading, the simplest way to address those
    issues is to reconfigure the server to revert to the previous default
    authentication plugin (mysql_native_password). For example, use these lines
    in the server option file:

    [mysqld]
    default_authentication_plugin=mysql_native_password

    However, the setting should be viewed as temporary, not as a long term or
    permanent solution, because it causes new accounts created with the setting
    in effect to forego the improved authentication security.
    If you are using replication please take time to understand how the
    authentication plugin changes may impact you.
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-compatibility-issues
    https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-replication

警告1について - Usage of utf8mb3 charset

ユニコードサポートを改善するために、文字コードはutf8mb4への変換を推奨 されています。

既存DBの文字コード変換については↓こちらの記事にまとめました。

https://hodalog.com/modify-the-character-encode-of-mysql/

警告2について - New default authentication plugin considerations

MySQL 8からデフォルトの認証プラグインが caching_sha2_password というものに変更されます。それに伴い問題が発生する可能性があるという内容の警告です。

新しいデフォルトの認証プラグイン ‘caching_sha2_password’は、以前使用されていた ‘mysql_native_password’よりも安全なパスワードハッシュを提供します。しかし既存のMySQLに影響を与える可能性もあります。

もしアップグレード後に問題が発生した場合は、次の環境変数を設定することで、暫定対策が可能なようです。

[mysqld]
default_authentication_plugin=mysql_native_password

MySQLダンプ-データの吸い出し

エラーと警告の対応ができたので、mysqldumpでデータを吸い出してバックアップをとります。

mysqldump db_name > backup-file.sql

コンテナの実行・動作確認

これまで一つのコンテナにPHP、MySQL、WordPress、Nginxを入れて動かしていたのですが、このマイグレーションを機に3つのマルチコンテナで運用することにしました。

使用するDockerイメージは下記の3つです。

  • php:7.3-fpm-alpine
  • nginx:1.15-alpine
  • mysql:8

ディレクトリ構成

今回は下記のような構成で行きました。

.
├── DockerfileNginx
├── DockerfileWeb
├── code
│   ├── certificate
~   ~   └── #ここに証明書ファイルなどを置く
│   ├── db
│   │   ├── .env #DBのユーザやパスワードの情報を格納したファイル
│   │   └── backup-file.sql #MySQLのダンプデータ
│   ├── nginx
│   │   └── conf.d
│   │       └── nginx.conf #Nginxのコンフィグデータ
│   └── web
~   ~   └── #ここにWordPressのディレクトリを置く
└── docker-compose.yml

DockerfileNginx

NginxコンテナのDockerfileです。証明書の更新にCertbotを使うため、ここでインストールしています。

FROM nginx:1.15-alpine
RUN apk --update upgrade \
    && apk add --no-cache --no-progress certbot \
    && mkdir -p /etc/letsencrypt/live /var/www/html

DockerfileWeb

WordPressを動かすためのDockerfileです。WordPressのイメージをそのまま使うか悩みましたが、WordPressのディレクトリは私の方でバックアップしたものをそのまま使いたかったため、PHPのイメージを採用し、WordPressの公式イメージのDockerfileを流用しています。

docker-compose.yml

YMLファイルの中身です。詳細は省きますが、MySQLの初期ユーザやパスワード、データベースを起動時にセットアップしたり、全て自動で設定が完了するように仕掛けています。

version: '3.7'

services:
    db:
      container_name: hodalog_db
      image: mysql:8
      command: --default-authentication-plugin=mysql_native_password
      env_file: ./code/db/.env
      volumes:
        - db_data:/var/lib/mysql
        - ./code/db/backup-file.sql:/docker-entrypoint-initdb.d/backup-file.sql
      ports:
        - "3306"
    web:
      container_name: hodalog_web
      build:
        context: .
        dockerfile: DockerfileWeb
      volumes:
        - ./code/web:/var/www/html
      ports:
        - "9000"
      depends_on:
        - db
    nginx:
      container_name: hodalog_nginx
      build:
        context: .
        dockerfile: DockerfileNginx
      volumes:
        - ./code/web:/var/www/html
        - ./code/nginx/conf.d:/etc/nginx/conf.d
        - ./code/certificate:/etc/letsencrypt/live
      ports:
        - "80:80"
        - "443:443"
      depends_on:
        - web
volumes:
    db_data:

このYMLファイルで指定したサービス名とポート番号に合わせて、Nginxのコンフィグとwp-config.phpは少し修正します。

# nginx.conf
server {
        listen          80;
        server_name    your-domain.com;
        expires         $expires;
        root /var/www/html/hogehoge;
        ...
        location ~ \.php$ {
                ...
                fastcgi_pass wordpress:9000; #←これ
                ...
        }
# wp-config.php
define('DB_HOST', 'db:3306');

移行先の準備

よしなに移行先を用意します。

監視の停止

モニタリングしている場合は止めます。私はUptimeRobotでpingとport監視、Mackerelでメトリクス監視をしていたので、一旦全部止めました。

切り替え作業

先のdockerファイルとYMLファイル、WordPressとSQLのバックアップ、SSL/TLS証明書一式を移行先へ持ち込み、デプロイします。

デプロイ後、エラーなどが発生していないか確認。今回はdocker-composeでデプロイしたので、 docker container logsdocker-compose logs などで確認しました。

私はAWS内でのお引越しだったため、Route 53のゾーンはそのままに、ElasticIPを古いインスタンスから新しいインスタンスへ付け替えるだけで完了しました。

まとめ

Amazon LinuxからAmazon Linux2へのマイグレーションが無事完了しました。合わせてコンテナの分割とPHP7.1→7.3、MySQL5.7→8.0へのバージョンアップも終わり、非常にスッキリした環境に生まれ変わりました。

レガシーな手法ではありますが、インフラ周りの基本的な整備や扱いはもうバッチリですね。HexoやNuxt.js、Gatsbyなどの静的ジェネレータが気になっているので、転機がきたらそちらへ移行します。