🐳

docker composeで本番運用に耐えられるWordPressを立ち上げる

2024/04/30に公開

概要

  • クイックにWordpressを動かせる環境が欲しかったのでdocker composeで立ち上げられるようにしました。
  • 本番運用にも使えるように、動的に追加されるデータはファイルシステム上に保管されて永続化されるようにしました。
  • 良い感じのサンプルが見つからなかったので作成しました。

成果物

以下に置きました。forkして使うのが良いと思います。

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

説明

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}

セットアップ

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

% git clone git@github.com: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です。

alt text

ユースケース

このテンプレートの良いところは既存のオンプレで運用しているWordpressから簡単に移行できることと、ホストOS側でバックアップが取りやすいというところです。

以下に運用時に想定される様々なユースケースに対するコマンド実行例を記載しておきます。

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

% 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

新しいWordPressサイトを立ち上げる方法

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

そのためには、WordpPressのコンテナの定義をコピペして一部ハードコードして使うのが良いと思います。
また、複数の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のバージョン更新

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

PHPの設定変更

Dockerhubから提供されているデフォルトのWordpPressにおいて、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

削除

環境を潰して、元どうりにする場合の方法

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

フルバックアップ

一時停止するけど簡単な方法。

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

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

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

まとめ

  • WordPressを簡単に立ち上げられるテンプレを用意しました。
  • MySQLが起動直後でも200MBぐらい消費するので要注意です。128MBに制限したらメモリ不足で立ち上がりませんでした。
  • 細かいところにこだわった良い感じの設定です。

Discussion