1669 文字
8 分

WordPressをDockerizedしました

概要#

クイックにWordPressを動かせる環境が欲しかったのでDocker composeで立ち上げられるようにしました。本番運用にも使えるように、動的に追加されるデータはファイルシステム上に保管されて永続化されるようにしています。

テンプレートリポジトリを用意したので、forkして使うのが手っ取り早いです。

https://github.com/matsubo/wordpress-docker-template

サーバ運用#

まず、Lightsail (月にで個人開発のサービスを一部運用していたのですが、データ量が多くなってきたのでストレージが足りなくなってきたことと、物理RAMが足りなくなってきたので自宅サーバへ移動しました。

Lightsailは以下のインスタンスを使っていました。

自宅サーバ自体もオーバースペック過ぎて、電気消費が大きいので新規に調達しました。

調達したPCはこちら。

Linux

自宅サーバー用にGMKtec Nucbox M2(Intel Core i7)を買ったのでレビュー

自宅サーバ用にGMKtec Nucbox M2(Core i7/32GB/1TB SSD)を53,000円で購入。CINEBENCHベンチマーク結果やUbuntu 22でのWiFiドライバ問題など実使用レポートを公開。

2024/04/02
自宅サーバー用にGMKtec Nucbox M2(Intel Core i7)を買ったのでレビュー

安くて良いです

サービス運用#

物理RAMが32GBあり、しばらく運用している現状で20GBぐらい使っています。

すべてのサービスをDockerizedしました。

DockerのRAMの利用常用はこんな感じです。

コンテナ数は30個ぐらいです。

RAMをたくさん使っているのは、MySQLとRailsのアプリケーションサーバです。RSS領域で使っています。あとは、disk cacheとしてちょこちょこ使われています。

WordPressサイトは10個ぐらいあります。1サイトごとにMySQLを立てているとメモリのMySQLサーバを立ち上げた直後の初期メモリ分が無駄になってしまうのでMySQLサーバは共有にしてアプリケーションサーバだけコンテナを個別にしました。MySQLは起動直後でも200MBぐらい消費するので、サイトごとに立てると馬鹿にならないです。128MBに制限したらメモリ不足で立ち上がりませんでした。

1.5ヶ月ほど運用していますが問題は起きていないし速度もLightsailに比べるとだいぶ速いです。

Docker Composeの設定#

設定を作るときにこだわったポイントは以下です。

  • 動的に生成されるMySQLのデータや、WordPressでアップロードしたメディアやプラグイン、テーマはファイルシステム上に保存される
  • 必要最低限のパーミッションなので万が一クラックされても汚染されるスコープが狭い
  • WordPress本体のバージョンの更新はイメージで行い、プラグインやテーマの更新はWeb上から動的に行える

単一サイト構成#

以下が docker-compose.yml です。

services:
mysql:
user: "${UID:-1000}:${GID:-1000}"
image: mysql:latest
restart: always
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf/custom.cnf:/etc/mysql/conf.d/custom.cnf
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE:-wordpress}
MYSQL_USER: ${MYSQL_USER:-root}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
wordpress:
image: wordpress:latest
user: "${UID:-1000}:${GID:-1000}"
restart: always
volumes:
- ./wordpress/themes:/var/www/html/wp-content/themes
- ./wordpress/plugins:/var/www/html/wp-content/plugins
- ./wordpress/uploads:/var/www/html/wp-content/uploads
links:
- mysql
depends_on:
- mysql
ports:
- "${EXPOSE_PORT:-8080}:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_NAME: ${MYSQL_DATABASE:-wordpress}
WORDPRESS_DB_USER: ${MYSQL_USER:-root}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}

複数サイト構成(MySQL共有)#

MySQLコンテナをWordPressごとに立ち上げるとメモリを消費してしまうので、MySQLを1つ立ち上げて複数のWordPressサイトから接続して使うほうが効率的です。

WordPressのコンテナの定義をコピー&ペーストして一部ハードコードして使います。複数のDBを扱うのでMySQLではrootで作業する必要が出てきます。

services:
mysql:
user: "${UID:-1000}:${GID:-1000}"
image: mysql:latest
restart: always
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf/custom.cnf:/etc/mysql/conf.d/custom.cnf
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_ROOT_HOST: '%'
production:
image: wordpress:latest
user: "${UID:-1000}:${GID:-1000}"
restart: always
volumes:
- ./production/themes:/var/www/html/wp-content/themes
- ./production/plugins:/var/www/html/wp-content/plugins
- ./production/uploads:/var/www/html/wp-content/uploads
links:
- mysql
depends_on:
- mysql
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_NAME: production
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}
staging:
image: wordpress:latest
user: "${UID:-1000}:${GID:-1000}"
restart: always
volumes:
- ./staging/themes:/var/www/html/wp-content/themes
- ./staging/plugins:/var/www/html/wp-content/plugins
- ./staging/uploads:/var/www/html/wp-content/uploads
links:
- mysql
depends_on:
- mysql
ports:
- "8081:80"
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_NAME: staging
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: ${MYSQL_ROOT_PASSWORD}

自分の環境ではこの複数サイト構成を使っています。

WordPressの大まかなインフラ設定#

  • DBは1コンテナ
  • WordPressのコンテナはオフィシャルのイメージを使っています。latestタグ。
  • theme, uploads, pluginsの3つのディレクトリはローカルのファイルシステムに保存してコンテナ側からマウントしています。

1つのdocker-compose.ymlに上記の設定を入れています。

1点、運用上ちょっと微妙なところはdocker compose経由でサービスを立ち上げると一気にコンテナを立ち上げてしまうので起動直後はCPU、Diskの負荷が増大します。

依存関係をつけて順番に起動していくように書いても良いですが、実際には依存関係がないし順番の管理が面倒なので割愛します。

セットアップ#

テンプレートとなるリポジトリをcloneしてきます。

% git clone [email protected]:matsubo/wordpress-docker-template.git
% cd wordpress-docker-template

以下のコマンドを打って動作に必要な環境変数を一通り自動で作成します。

echo -n > .env
echo "MYSQL_DATABASE=wordpress" >> .env
echo "MYSQL_USER=wordpress" >> .env
echo "MYSQL_ROOT_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 15)" >> .env
echo "MYSQL_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 15)" >> .env
echo "EXPOSE_PORT=8080" >> .env
echo "UID=$(id -u)" >> .env
echo "GID=$(id -g)" >> .env

そのあと、docker compose up すれば初期設定が行われて、サーバ環境が立ち上がります。

% docker compose up

ブラウザでアクセスすれば初期設定画面が出るので、そのまま進めればOKです。

既存のWordPressからDockerに移行する方法#

オンプレで運用しているWordPressから移行する場合は以下の手順でいけます。

% cp -ra /old/wordpress/wp-content/{plugins,themes,uploads} wordpress/
% mysqldump -u ${OLD_MYSQL_USER} --password=${OLD_MYSQL_PASSWORD} ${OLD_MYSQL_DB_NAME} | bzip2 > dump.sql.bz2
% docker compose cp dump.sql.bz2 mysql:/dump.sql.bz2
% docker compose exec mysql bash -c 'bzcat /dump.sql.bz2 | mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE'
% docker compose exec mysql bash rm /dump.sql.bz2

wp-contentの中身をコピーして、DBをdumpしてコンテナに流し込むだけなので簡単です。

PHPの設定変更#

Dockerhubから提供されているデフォルトのWordPressイメージでは、HTTP経由でアップロードできるファイルサイズの最大容量がたった2MBしかないです。

増やすためにはphp.iniによって設定をoverrideする必要があります。

wordpress/custom.ini にファイルを作って中身を以下のように追加します。

post_max_size = 50M
upload_max_filesize = 50M

あとはWordPressのイメージを起動する際に上記のファイルをマウントしてしまえばよいだけです。

volumes:
- ./wordpress/custom.ini:/usr/local/etc/php/conf.d/custom.ini

WordPressのバージョン更新#

% docker pull wordpress:latest
% docker compose down && docker compose up -d

バックアップとリストア#

クラウドじゃなくなったのでバックアップをしっかり取っていく必要があります。

ホストOS側でバックアップが取りやすいのがこの構成の良いところです。一時停止が許容できるなら以下のtarで丸ごとバックアップするのが一番簡単です。

フルバックアップ#

% docker compose down
% tar jcf /path/to/backup.tar.bz2 .

フルバックアップからのリストア#

% tar xf /path/to/backup.tar.bz2

環境の削除#

環境を潰して元どおりにする場合。

% docker compose down
% rm -rf mysql/data/*
% rm -rf wordpress/*/*

今後#

ハードウェア故障に対してのBCPを考えていきます。

WordPressをDockerizedしました
https://blog.teraren.com/posts/wordpress-dockerized/
作者
Yuki Matsukura
公開日
2024-06-15
ライセンス
CC BY-NC-SA 4.0
この記事が役に立ったら
GitHub Sponsorsで応援できます

コメント