【Podman】別々のサーバーで運用しているWordPressを、Podmanで1つのMariaDBコンテナ + 2つのWordPressコンテナ環境に移行する方法

記事内に広告が含まれています。

それぞれ異なるサーバーで運用していた複数のWordPressサイトを、1台の新サーバー(AlmaLinux 10)に移行し、「ホストOS側のNginx」+「Podman上の1つのMariaDBコンテナと2つのWordPressコンテナ」という構成にする手順を解説します。

  1. 今回構築する構成
  2. 旧サーバーでのバックアップ
    1. WordPress公開ファイルのバックアップ
    2. データベースのエクスポート
    3. 新サーバーへバックアップファイルを転送
  3. 新サーバー(移行先)でのPodman環境の作成
    1. Podmanインストール
    2. compose.yaml作成
  4. WordPressデータのリストア
    1. 名前付きボリュームの作成
    2. WordPressバックアップデータのインポート
    3. ファイル所有者(権限)の調整
  5. データベースの作成とリストア
    1. MariaDBコンテナの先行起動
    2. 各サイト用データベースの作成
    3. 接続用ユーザーの作成と権限付与
    4. データのリストア(SQLインポート)
  6. wp-config.php の修正(DB接続情報とHTTPS設定)
  7. コンテナ起動
    1. 起動の確認
    2. コンテナの停止
  8. コンテナの自動起動設定(Quadlet)
    1. 設定ファイル用ディレクトリの作成
    2. ネットワーク定義ファイルの作成(wordpress.network)
    3. コンテナ定義ファイルの作成(.container)
    4. systemdの再読み込みとサービスの起動
    5. ユーザー常駐(Linger)の有効化
  9. ホストOS側のNginx設定(リバースプロキシ用)
    1. Nginxインストール
    2. certbotインストール
    3. Let's Encrypt用ディレクトリ作成
    4. テスト用SSL/TLS証明書と秘密鍵を用意
    5. リバースプロキシ用設定
    6. サイト1用のNginx設定ファイル作成
    7. サイト2用のNginx設定ファイル作成
    8. 設定反映と事前動作確認
  10. サーバー切り替え作業
    1. DNS切り替え
    2. Let's EncryptでSSL/TLS証明書の再取得
    3. 最終動作確認
  11. まとめ

今回構築する構成

移行前は別々のサーバーで動いていた環境を、新サーバー(AlmaLinux 10)上では以下のように1つの compose.yaml でスッキリまとめます。

[クライアント]
      │
      ▼
[ホスト側 Nginx]
      │
      ├ (:8081) ─> [WordPress site1] ─┐
      │                                 │
      └ (:8082) ─> [WordPress site2] ─┴─> [共有 MariaDB (wp_db)]
                                                  ├── データベース: db_site1
                                                  └── データベース: db_site2

旧サーバーでのバックアップ

移行元の旧サーバー(サーバー1、サーバー2)それぞれにログインし、WordPressの「公開ファイル」と「データベース」をバックアップして新サーバーへ転送します。

WordPress公開ファイルのバックアップ

WordPressがインストールされているディレクトリ(例: /var/www/html/site1 など)の中身を丸ごとtarでバックアップします。

# サーバー1(サイト1)の場合
sudo tar -czvf site1_files.tar.gz -C /var/www/html/site1 .

# サーバー2(サイト2)の場合
sudo tar -czvf site2_files.tar.gz -C /var/www/html/site2 .

※末尾の半角スペースと「.」を忘れずに入力してください。「-C ディレクトリ名 .」と指定することで、親ディレクトリ階層を含めず「中身のファイルだけ」をアーカイブできます(これを省いてフルパスで固めると、後でコンテナのボリュームに展開した際に階層が二重になってしまいます)。

データベースのエクスポート

それぞれの旧サーバーにある「wp-config.php」を確認し、記載されている接続情報を使ってmysqldumpを実行します。

  • DBユーザー名: DB_USER の値
  • DBパスワード: DB_PASSWORD の値
  • DB名: DB_NAME の値
# サーバー1(サイト1)の場合
mysqldump -u DBユーザー名 -p'DBパスワード' \
  --default-character-set=utf8mb4 \
  --single-transaction \
  --hex-blob \
  --quick \
  DB名 > site1_backup.sql

# サーバー2(サイト2)の場合
mysqldump -u DBユーザー名 -p'DBパスワード' \
  --default-character-set=utf8mb4 \
  --single-transaction \
  --hex-blob \
  --quick \
  DB名 > site2_backup.sql

※パスワードは「-p'パスワード'」と直接続けるか、「-p」のみ指定して対話型で入力します。

新サーバーへバックアップファイルを転送

バックアップしたファイル(tar.gz と .sql)を新サーバーへ転送します。

# サーバー1(サイト1)から転送する場合
scp site1_files.tar.gz site1_backup.sql 新サーバーのユーザー名@新サーバーIP:~/

# サーバー2(サイト2)から転送する場合
scp site2_files.tar.gz site2_backup.sql 新サーバーのユーザー名@新サーバーIP:~/

※ 転送方法は「scp」や「sftp」など使いやすい方法で問題ありません。

新サーバー(移行先)でのPodman環境の作成

Podmanインストール

新サーバーに「Podman」および「Podman Compose」をインストールします。

sudo dnf install podman podman-compose

compose.yaml作成

新サーバー側で、すべてのコンテナを統合管理する「compose.yaml」を「~/wordpress」ディレクトリに作成します。

今回は、DBコンテナのメモリ消費を抑えるため、1つのMariaDBコンテナを共有する設計です。

mkdir ~/wordpress
cd ~/wordpress
vi compose.yaml

設定内容

コンテナ名などは、環境に合わせて自分で分かりやすい名前を設定してください。

※名前を変更した場合は、これ以降の手順でも適宜読み替えて作業を行ってください。

services:
  # ─── 統合する1つの共通MariaDBコンテナ ───
  wp_db:
    image: docker.io/library/mariadb:11.4
    container_name: wp_db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: secure_root_password
      TZ: Asia/Tokyo
    volumes:
      - db_data:/var/lib/mysql

  # ─── 旧サーバーから移行するサイト1 ───
  site1:
    image: docker.io/library/wordpress:latest
    container_name: site1
    restart: always
    environment:
      TZ: Asia/Tokyo
    ports:
      - "127.0.0.1:8081:80" # ホストOSのnginxからは8081へ転送
    volumes:
      - site1_data:/var/www/html
    depends_on:
      - wp_db

  # ─── 旧サーバーから移行するサイト2 ───
  site2:
    image: docker.io/library/wordpress:latest
    container_name: site2
    restart: always
    environment:
      TZ: Asia/Tokyo
    ports:
      - "127.0.0.1:8082:80" # ホストOSのnginxからは8082へ転送
    volumes:
      - site2_data:/var/www/html
    depends_on:
      - wp_db

volumes:
  db_data:
  site1_data:
  site2_data:

ports設定で「127.0.0.1:8081:80」のようにローカルホスト(127.0.0.1)を指定することで、外部からの直接アクセスを防ぎ、ホストOSのNginx経由でのみアクセスを許可するセキュアな構成にしています。

また、環境変数「TZ: Asia/Tokyo」を指定してコンテナ内の時刻を日本標準時(JST)に合わせています。

WordPressデータのリストア

WordPressコンテナを起動する前に、あらかじめ名前付きボリュームを作成してバックアップデータを展開しておきます。

あらかじめデータを配置しておくことで、コンテナ初回起動時にWordPress公式イメージが新規ファイルを自動展開(上書き)してしまうのを防ぎ、旧サーバーの環境をそのまま安全に引き継ぐことができます。

名前付きボリュームの作成

バックアップデータを展開するための「受け皿」となる名前付きボリュームを先行して作成します。

podman volume create wordpress_site1_data
podman volume create wordpress_site2_data

なぜボリューム名に「wordpress_」を付けるのか?

「compose.yaml」内では「site1_data」「site2_data」と定義していますが、Composeはプロジェクトディレクトリ名(今回は wordpress)を接頭辞として自動付与するため、実際に作成されるボリューム名は「wordpress_site1_data」「wordpress_site2_data」になります。そのため、手動で先行作成・インポートを行う際もこの名前を指定します。

WordPressバックアップデータのインポート

Podman標準の「volume import」コマンドを使い、各サイトのバックアップアーカイブをそれぞれのボリュームに直接展開します。

※バックアップファイルの配置場所が異なる場合は、適宜パスを読み替えて実行してください。

podman volume import wordpress_site1_data ~/site1_files.tar.gz
podman volume import wordpress_site2_data ~/site2_files.tar.gz

ファイル所有者(権限)の調整

インポートしたファイルは旧サーバーの所有者(UID/GID)のまま展開されているため、このままではWordPressからファイルの更新やアップロードができず、書き込み権限エラーが発生します。

WordPress公式イメージ(Apache版)は、内部で「www-data」ユーザー(UID: 33 / GID: 33)として動作しています。
そのため、一時的な軽量コンテナ(Alpine Linux)を起動し、ボリューム内の全ファイルの所有者を「33:33」に変更します。

podman run --rm -v wordpress_site1_data:/target alpine chown -R 33:33 /target
podman run --rm -v wordpress_site2_data:/target alpine chown -R 33:33 /target

※「--rm」オプションを指定しているため、権限変更の処理が終わると一時コンテナは自動的に破棄されます。

データベースの作成とリストア

1つのMariaDBコンテナ内に、サイト1とサイト2それぞれのデータベースと接続ユーザーを作成し、旧サーバーから取得したバックアップデータを順番にインポートします。

MariaDBコンテナの先行起動

データベースの作成やリストアを行うため、まずはMariaDBコンテナのみを起動します。

cd ~/wordpress
podman-compose up -d wp_db

各サイト用データベースの作成

起動したMariaDBコンテナ(wp_db)内で、各サイト用のデータベースを新規作成します。

コマンド構文

実行するコマンドの構文は以下の通りです。

  • MariaDBコンテナ: 「compose.yaml」の「container_name」で設定した名前(例: wp_db)
  • MariaDBのrootパスワード: 「compose.yaml」の「MYSQL_ROOT_PASSWORD」で設定したパスワード
  • 作成するDB名: 各サイトの「wp-config.php」の「DB_NAME」で設定されている名前

※DB名を変更したい場合は、後述する「wp-config.php」の編集時に合わせて「DB_NAME」部分も変更が必要になります。

podman exec -it MariaDBコンテナ mariadb \
  -u root -p'MariaDBのrootパスワード' \
  -e "CREATE DATABASE IF NOT EXISTS 作成するDB名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

実行例

以下の内容が「wp-config.php」に設定されていたとして実行しています。

  • サイト1 DB_NAME: db_site1
  • サイト2 DB_NAME: db_site2
# サイト1用データベース(db_site1)の作成
podman exec -it wp_db mariadb \
  -u root -p'secure_root_password' \
  -e "CREATE DATABASE IF NOT EXISTS db_site1 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# サイト2用データベース(db_site2)の作成
podman exec -it wp_db mariadb \
  -u root -p'secure_root_password' \
  -e "CREATE DATABASE IF NOT EXISTS db_site2 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

接続用ユーザーの作成と権限付与

各WordPressコンテナが対応するデータベースにアクセスできるよう、専用の接続ユーザーを作成して権限を付与します。

コマンド構文

実行するコマンドの構文は以下の通りです。

  • MariaDBコンテナ: 「compose.yaml」の「container_name」で設定した名前(例: wp_db)
  • MariaDBのrootパスワード: 「compose.yaml」の「MYSQL_ROOT_PASSWORD」で設定したパスワード
  • DBユーザー: 各サイトの「wp-config.php」の「DB_USER」で設定されている名前
  • DBパスワード: 各サイトの「wp-config.php」の「DB_PASSWORD」で設定されているパスワード
  • DB名: 一つ前の手順で作成したDB名
podman exec -it MariaDBコンテナ mariadb -u root -p'MariaDBのrootパスワード' -e "
CREATE USER IF NOT EXISTS 'DBユーザー'@'%' IDENTIFIED BY 'DBパスワード';
GRANT ALL PRIVILEGES ON DB名.* TO 'DBユーザー'@'%';
FLUSH PRIVILEGES;"

※「DBユーザー」「DBパスワード」を変更する場合は、後述する「wp-config.php」の編集時に合わせて変更が必要になります。

実行例

以下の内容が「wp-config.php」に設定されていたとして実行しています。

  • サイト1 DB_USER: user_site1
  • サイト1 DB_PASSWORD: db_password_site1
  • サイト1 DB_NAME: db_site1
  • サイト2 DB_USER: user_site2
  • サイト2 DB_PASSWORD: db_password_site2
  • サイト2 DB_NAME: db_site2
# サイト1用ユーザーの作成と権限付与
podman exec -it wp_db mariadb -u root -p'secure_root_password' -e "
CREATE USER IF NOT EXISTS 'user_site1'@'%' IDENTIFIED BY 'db_password_site1';
GRANT ALL PRIVILEGES ON db_site1.* TO 'user_site1'@'%';
FLUSH PRIVILEGES;"

# サイト2用ユーザーの作成と権限付与
podman exec -it wp_db mariadb -u root -p'secure_root_password' -e "
CREATE USER IF NOT EXISTS 'user_site2'@'%' IDENTIFIED BY 'db_password_site2';
GRANT ALL PRIVILEGES ON db_site2.* TO 'user_site2'@'%';
FLUSH PRIVILEGES;"

# ユーザーが正しく作成されたかの確認
podman exec -it wp_db mariadb -u root -p'secure_root_password' -e "
SELECT User, Host FROM mysql.user WHERE User IN ('user_site1', 'user_site2');"
+------------+------+
| User       | Host |
+------------+------+
| user_site1 | %    |
| user_site2 | %    |
+------------+------+

データのリストア(SQLインポート)

作成したデータベースへ、転送しておいたSQLバックアップファイルを順番にインポートします。

コマンド構文

podman exec -i DBコンテナ名 mariadb -u root -p'MariaDBのrootパスワード' DB名 < バックアップ.sql

実行例

# サイト1のリストア
podman exec -i wp_db mariadb -u root -p'secure_root_password' db_site1 < ~/site1_backup.sql

# サイト2のリストア
podman exec -i wp_db mariadb -u root -p'secure_root_password' db_site2 < ~/site2_backup.sql

wp-config.php の修正(DB接続情報とHTTPS設定)

旧サーバーからリストアしたデータには、旧サーバー環境の「wp-config.php」が含まれています。

このままでは、接続するDBサーバーのホスト名が、本環境のMariaDBコンテナではなく旧環境のDBサーバー(localhostなど)を参照してしまい、「データベース接続確立エラー」が発生してしまうため、新環境のMariaDBコンテナに接続するようにボリューム内の「wp-config.php」を編集します。

※ DBを作成する際に、DB名を変更したり、接続用ユーザーの名前やパスワードを変更した場合も、それにあわせて変更を行う必要があります。

一時コンテナ(Alpine Linux)の標準viで開くと日本語コメントが文字化けしてしまうため、「podman unshare」コマンドを使い、ホストOS側の日本語対応エディタ(viなど)で直接編集するのが最も確実です。

# サイト1の設定編集
podman unshare vi ~/.local/share/containers/storage/volumes/wordpress_site1_data/_data/wp-config.php

# サイト2の設定編集
podman unshare vi ~/.local/share/containers/storage/volumes/wordpress_site2_data/_data/wp-config.php

「podman unshare」を実行することで、直前に変更した所有者(33:33)によるパーミッションエラーを防ぎ、コンテナ内root相当の権限でホスト側エディタを開くことができます。

もし「vi」で開いた際に行末に「^M」と表示される場合は、過去にWindows環境等で編集されたことによる改行コード(CRLF)が残っているためです。
事前に以下のsedコマンドを実行して「^M」を一括削除(Linux標準のLF改行に統一)しておくと安全です。

# 行末の ^M(CRコード)を一括削除する場合
podman unshare sed -i 's/\r$//' ~/.local/share/containers/storage/volumes/wordpress_site1_data/_data/wp-config.php
podman unshare sed -i 's/\r$//' ~/.local/share/containers/storage/volumes/wordpress_site2_data/_data/wp-config.php

データベース接続情報の変更

新サーバーの設定に合わせて、該当する部分を書き換えます。

「DB_HOST」には、「compose.yaml」で設定したMariaDBのコンテナ名(container_name)を指定してください。

/** データベース名 */
define( 'DB_NAME', '作成したDB名' );       // 例: db_site1

/** データベースのユーザー名 */
define( 'DB_USER', '作成したユーザー名' );   // 例: user_site1

/** データベースのパスワード */
define( 'DB_PASSWORD', '設定したパスワード' );  // 例: db_password_site1

/** データベースのホスト名 */
define( 'DB_HOST', 'wp_db' );       // 重要: MariaDBのコンテナ名を指定

HTTPS対応(リバースプロキシ環境下のリダイレクトループ防止)の追記

ホスト側のNginxでSSL(HTTPS)を処理してコンテナへHTTP転送している場合、以下の設定がないとWordPressが「HTTPでアクセスされた」と誤認し、無限リダイレクトループ(ERR_TOO_MANY_REDIRECTS)やCSS・画像が表示されない不具合が発生します。

Nginxから渡されるヘッダーを読み取り、HTTPSアクセスとして正しく処理させるため、以下のコードを「wp-config.php」内(「require_once ABSPATH . 'wp-settings.php';」より前)に追記します。

/* Add any custom values between this line and the "stop editing" line. */


/* 追加設定  リバースプロキシ(Nginx)環境下でのHTTPS認識 */
if (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https') {
    $_SERVER['HTTPS'] = 'on';
}


/* That's all, stop editing! Happy publishing. */

/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
        define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

コンテナ起動

すべてのインポートと設定ファイルの修正が完了したら、全コンテナを起動します。

podman-compose up -d

起動の確認

コンテナが起動しているかの確認を行います。

podman-compose ps
CONTAINER ID  IMAGE                               COMMAND               CREATED        STATUS        PORTS                   NAMES
25ed8fce5e4f  docker.io/library/mariadb:11.4      mariadbd              2 hours ago    Up 2 hours    3306/tcp                wp_db
fa5e15fd8ecf  docker.io/library/wordpress:latest  apache2-foregroun...  4 seconds ago  Up 4 seconds  127.0.0.1:8081->80/tcp  site1
c4e18573d250  docker.io/library/wordpress:latest  apache2-foregroun...  4 seconds ago  Up 4 seconds  127.0.0.1:8082->80/tcp  site2

STATUSが「Up」になっていれば、コンテナは起動しています。

コンテナの停止

コンテナが起動することを確認できたら、自動起動設定を行うのでコンテナを停止します。

podman-compose down

コンテナの自動起動設定(Quadlet)

サーバー再起動時にもコンテナが自動的に立ち上がるよう、Podman標準の機能である「Quadlet(クアドラット)」を設定します。

以前使われていた「podman generate systemd」は非推奨となっており、現在は設定ファイルを配置するだけでsystemdサービスを自動生成してくれるQuadletを使用するのが標準です。

設定ファイル用ディレクトリの作成

コンテナを実行している一般ユーザーで、Quadlet用の設定ディレクトリを作成します。

mkdir -p ~/.config/containers/systemd

ネットワーク定義ファイルの作成(wordpress.network)

コンテナ同士が「wp_db」という名前で通信できるよう、共通のブリッジネットワークを定義します。

vi ~/.config/containers/systemd/wordpress.network

設定内容は以下のとおりです。

[Network]
NetworkName=wordpress_net

コンテナ定義ファイルの作成(.container)

各コンテナの設定ファイルを作成します。

「Network=」には、先ほど作成したネットワーク定義ファイル名「wordpress.network」を指定します。

これにより、コンテナ起動前に「systemd」がネットワークを自動作成してくれるようになります。

MariaDBコンテナ用(wp_db.container)

MariaDB用コンテナ(wp_db)の設定を作成します。

vi ~/.config/containers/systemd/wp_db.container

設定内容は以下のとおりです。

[Unit]
Description=MariaDB Database for WordPress

[Container]
ContainerName=wp_db
Image=docker.io/library/mariadb:11.4
Environment=MYSQL_ROOT_PASSWORD=secure_root_password
Volume=wordpress_db_data:/var/lib/mysql
Network=wordpress.network
Timezone=Asia/Tokyo

[Install]
WantedBy=default.target

サイト1用WordPressコンテナ(site1.container)

サイト1用WordPressコンテナ(site1)の設定を作成します。

vi ~/.config/containers/systemd/site1.container

「After=」と「Requires=」を指定することで、必ずMariaDBコンテナが起動してからWordPressが起動するように依存関係を制御します。

[Unit]
Description=WordPress Site 1
After=wp_db.service
Requires=wp_db.service

[Container]
ContainerName=site1
Image=docker.io/library/wordpress:latest
PublishPort=127.0.0.1:8081:80
Volume=wordpress_site1_data:/var/www/html
Network=wordpress.network
Timezone=Asia/Tokyo

[Install]
WantedBy=default.target

サイト2用WordPressコンテナ(site2.container)

サイト2用WordPressコンテナ(site2)の設定を作成します。

vi ~/.config/containers/systemd/site2.container

設定内容は以下のとおりです。

[Unit]
Description=WordPress Site 2
After=wp_db.service
Requires=wp_db.service

[Container]
ContainerName=site2
Image=docker.io/library/wordpress:latest
PublishPort=127.0.0.1:8082:80
Volume=wordpress_site2_data:/var/www/html
Network=wordpress.network
Timezone=Asia/Tokyo

[Install]
WantedBy=default.target

systemdの再読み込みとサービスの起動

設定ファイルを配置したら、「systemd」を再読み込みしてサービスを起動します。

# 設定ファイルの再読み込み
systemctl --user daemon-reload

# サービスの起動
systemctl --user start wp_db site1 site2

「.container」ファイル内に「WantedBy=default.target」を記述しているため、「daemon-reload」を実行した時点で自動起動の有効化は完了しています。

そのため手動で「systemctl enable」を実行する必要はなく(実行すると is transient or generated エラーになります)、「start」で起動するだけで次回サーバー起動時にも自動的に立ち上がります。

以下のコマンドでステータスを確認し、「active (running)」になっていれば正常に起動しています。

systemctl --user status site1
systemctl --user status site2
systemctl --user status wp_db

ユーザー常駐(Linger)の有効化

ルートレスPodmanでは、一般ユーザーがログアウトしてもバックグラウンドでコンテナを動かし続け、サーバー起動時にも自動起動させるために「Linger」の有効化が必須です。

loginctl enable-linger $USER

以下のコマンドで「Linger=yes」と表示されれば設定完了です。

loginctl show-user $USER -p Linger

Quadlet設定後の「compose.yaml」の扱いとコンテナ管理

「Quadlet」の設定完了後は、コンテナの起動・停止・自動起動のすべてを「systemd」が直接制御します。

そのため、「~/wordpress/compose.yaml」を削除してもコンテナの動作には一切影響しませんが、ポート番号やボリューム、環境変数といった全体構成がひと目でわかる「設計図」としてそのまま残しておくことをおすすめします。

注意点として、Quadletによる稼働中に「podman-compose up」などを実行すると、コンテナ名やポートの重複エラーが発生してしまいますので、日常の起動・停止や再起動は、すべて以下の「systemctl --user」コマンドで行うようにしてください。

# 全コンテナの停止
systemctl --user stop site1 site2 wp_db

# 全コンテナの起動
systemctl --user start wp_db site1 site2

# コンテナの再起動
systemctl --user restart site1 site2 wp_db

ホストOS側のNginx設定(リバースプロキシ用)

フロントに配置しているOS側の「Nginx」で、それぞれのドメイン宛てのアクセスを各WordPressコンテナのポートへ転送する設定をします。

Nginxインストール

最新版のNginxを利用するため、Nginxの公式リポジトリを使用して「Nginx」をインストールします。

Nginxリポジトリを作成

sudo vi /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

インストール

sudo dnf install nginx

自動起動設定

自動起動の設定と起動を同時に行います。

sudo systemctl enable --now nginx

certbotインストール

Let's EncryptでSSL証明書を取得するために必要なcertbotをインストールします。

sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx

Let's Encrypt用ディレクトリ作成

Let's EncryptのWeb認証(ACMEチャレンジ)で使用するディレクトリを作成します。

sudo mkdir -p /usr/share/nginx/site1
sudo mkdir -p /usr/share/nginx/site2

テスト用SSL/TLS証明書と秘密鍵を用意

DNS切り替え前にクライアントPCの「hosts」を使ってHTTPS接続による動作確認を行うため、旧サーバーで使用しているSSL/TLS証明書と秘密鍵を新サーバーへ一時的にコピーします。

「/etc/letsencrypt/live/」内のファイルはシンボリックリンクになっているため、実体ファイルをコピーできる「cp -L」コマンドを使って取り出します。

また、サイト1とサイト2でファイル名が重複しないよう名前を変更して新サーバーへ転送します。

サーバー1(サイト1)から証明書を転送

旧サーバー1にログインし、証明書と秘密鍵を取り出して新サーバーへ転送します。

# 実体ファイルを名前を変更してコピー
sudo cp -L /etc/letsencrypt/live/site1.example.com/fullchain.pem ./site1-fullchain.pem
sudo cp -L /etc/letsencrypt/live/site1.example.com/privkey.pem ./site1-privkey.pem

# 転送できるように所有者をログインユーザーに変更
sudo chown $USER:$USER ./site1-*.pem

# 新サーバーへ転送
scp site1-*.pem 新サーバーのユーザー名@新サーバーIP:~/

サーバー2(サイト2)から証明書を転送

旧サーバー2でも同様に、証明書と秘密鍵を取り出して新サーバーへ転送します。

# 実体ファイルを名前を変更してコピー
sudo cp -L /etc/letsencrypt/live/site2.example.com/fullchain.pem ./site2-fullchain.pem
sudo cp -L /etc/letsencrypt/live/site2.example.com/privkey.pem ./site2-privkey.pem

# 転送できるように所有者をログインユーザーに変更
sudo chown $USER:$USER ./site2-*.pem

# 新サーバーへ転送
scp site2-*.pem 新サーバーのユーザー名@新サーバーIP:~/

新サーバー側での配置とパーミッション設定

新サーバーに届いた証明書と秘密鍵を「/etc/nginx」へ移動し、パーミッションを設定します(セキュリティのため秘密鍵はrootのみ読み取り可能にします)。

# /etc/nginx へ移動
sudo mv ~/site1-*.pem /etc/nginx/
sudo mv ~/site2-*.pem /etc/nginx/

# 所有者をrootに変更
sudo chown root:root /etc/nginx/site*.pem

# パーミッション設定
sudo chmod 644 /etc/nginx/site*-fullchain.pem
sudo chmod 600 /etc/nginx/site*-privkey.pem

リバースプロキシ用設定

WordPress宛の通信をホスト側のNginxからWordPressコンテナへ転送する設定を行います。

複数のドメインを設定する際にも使い回せるよう、共通のプロキシ用ヘッダー定義ファイルを作成します。

sudo vi /etc/nginx/proxy_params

以下の内容を記述します。

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

サイト1用のNginx設定ファイル作成

サイト1用の設定ファイルを作成します。
※ここではsite1のドメイン名を「site1.example.com」としていますので、各自の環境に合わせて読み替えてください。

sudo vi /etc/nginx/conf.d/site1.conf

以下の内容を記述します。

# 転送先の設定
upstream site1 {
    server 127.0.0.1:8081 fail_timeout=0;
}

server {
    listen 443 ssl;
    server_name site1.example.com;
    root /usr/share/nginx/site1;
    index index.html;

    access_log /var/log/nginx/site1_access.log;
    error_log /var/log/nginx/site1_error.log;

    ssl_certificate /etc/nginx/site1-fullchain.pem;
    ssl_certificate_key /etc/nginx/site1-privkey.pem;

    # Let's Encrypt 更新用設定
    location ^~ /.well-known {
        root /usr/share/nginx/site1;
    }

    # リバースプロキシ設定(WordPressコンテナへ転送)
    location / {
        include proxy_params;
        proxy_pass http://site1;
    }
}

server {
    listen 80;
    server_name site1.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

サイト2用のNginx設定ファイル作成

サイト2用も同様に設定ファイルを作成します。

sudo vi /etc/nginx/conf.d/site2.conf

以下の内容を記述します。

# 転送先の設定
upstream site2 {
    server 127.0.0.1:8082 fail_timeout=0;
}

server {
    listen 443 ssl;
    server_name site2.example.com;
    root /usr/share/nginx/site2;
    index index.html;

    access_log /var/log/nginx/site2_access.log;
    error_log /var/log/nginx/site2_error.log;

    ssl_certificate /etc/nginx/site2-fullchain.pem;
    ssl_certificate_key /etc/nginx/site2-privkey.pem;

    # Let's Encrypt 更新用設定
    location ^~ /.well-known {
        root /usr/share/nginx/site2;
    }

    # リバースプロキシ設定(WordPressコンテナへ転送)
    location / {
        include proxy_params;
        proxy_pass http://site2;
    }
}

server {
    listen 80;
    server_name site2.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

設定反映と事前動作確認

「nginx -t」で書式の確認を行ってから、「Nginx」を再起動し設定を反映させます。

sudo nginx -t
sudo systemctl restart nginx

クライアントPCのhosts設定変更

クライアントPC(作業用PC)のhostsファイルを編集し、一時的に移行作業を行ったサイトが新サーバーのIPを向くように設定します。

ブラウザでの動作確認

Webブラウザで「https://site1.example.com」や「https://site2.example.com」にアクセスし、新サーバー上で問題なくWordPressの閲覧や管理画面へのログイン、記事の投稿・画像の表示ができるかを確認してください。

トップページ以外が「404 Not Found」になる場合

もし、トップページは表示されるのに記事ページや固定ページを開くと「404 Not Found」になる場合は、URLリライト用の「.htaccess」が存在しないことが原因です(特に旧環境がNginxだった場合、「.htaccess」が存在しないため必ず発生します)。

また、プラグイン等でログインURLを変更している場合、「.htaccess」がないとログイン画面自体も404になり管理画面に入れなくなってしまいます。

その場合は、新サーバー側で以下のコマンドを実行して直接「.htaccess」を作成してください。

ボリュームのパスはご自分の環境にあわせて適宜読み替えてください。

サイト1用
podman unshare sh -c 'cat << "EOF" > ~/.local/share/containers/storage/volumes/wordpress_site1_data/_data/.htaccess
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
EOF
chown 33:33 ~/.local/share/containers/storage/volumes/wordpress_site1_data/_data/.htaccess'
サイト2用
podman unshare sh -c 'cat << "EOF" > ~/.local/share/containers/storage/volumes/wordpress_site2_data/_data/.htaccess
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
EOF
chown 33:33 ~/.local/share/containers/storage/volumes/wordpress_site2_data/_data/.htaccess'

※コマンド末尾の「chown 33:33」で、作成したファイルの所有者をWordPress(www-data)に設定し、管理画面からの編集や書き込み権限を付与しています。

コマンド実行後、ブラウザをリロードすれば各ページや変更後のログイン画面が正常に表示されるようになります。

管理画面にログインできる状態であれば、「設定」-「パーマリンク」を開いて「変更を保存」をクリックすることでも同様に「.htaccess」を自動生成できます。

確認が完了したら、PCのhosts設定は元に戻しておきます。

サーバー切り替え作業

DNS切り替え

ドメインのDNS設定(Aレコード)を変更し、サイト1とサイト2のアクセス先を新サーバーのIPアドレスに切り替えます。

Let's EncryptでSSL/TLS証明書の再取得

DNSの切り替えが完了し、インターネット上から新サーバーにアクセスできることが確認できたら、「certbot」を実行して新サーバー上で正式にSSL/TLS証明書を取得します。

sudo certbot --nginx -d site1.example.com -m メールアドレス --agree-tos
sudo certbot --nginx -d site2.example.com -m メールアドレス --agree-tos

「--nginx」プラグインを指定しているため、コマンドが成功すると設定ファイル内の証明書パスが自動的にLet's Encrypt管理下のパス(/etc/letsencrypt/live/...)へ書き換えられ、Nginxへの設定反映(リロード)も自動的に完了します。

そのため、手動でNginxを再起動する必要はありません。

最終動作確認

Webブラウザでサイト1とサイト2にそれぞれHTTPSでアクセスし、問題なく表示されることを確認します。

ブラウザのアドレスバーにある鍵マークをクリックして証明書情報を開き、有効期間の開始日(発行日)が本日取得した日付に更新されていれば、すべての移行作業は完了です!

まとめ

別々のサーバーにあったWordPressでも、コンテナの「名前付きボリューム」と「独立したポート割り当て」を活用すれば、1つのMariaDBインスタンスに安全に集約・統合することができます。サーバーの運用コストやリソースを抑えたい方は、ぜひお試しください!

コメント

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