docker-compose を利用した WordPress 開発環境

ウェブ
[ docker-compose を利用した WordPress 開発環境 ]

ここ何年か利用してきた VCCW は放棄されていた模様 だったで、改めて環境を整えることにしました。この記事は、docker で効率を高めつつ VCCW 的な使い勝手を目指した備忘録です。

最初に。サーバ環境一式のみで足りる用途なら、類似の Vagrant 系で十分だと思います。ここでは、メインの開発環境と共に、雑多なバージョンの組み合わせの PHP + WordPress を効率よく作成/起動/終了/破棄して動作検証できる環境を作ります。

2012/12/12 追記。nginx/proxy.conf, nginx/default.conf, php/mysql.ini に設定を追加しました。タイムアウトの抑制、アップロードのファイル容量制限の緩和、リバースプロキシと FastCGI のバッファ不足の解消です。

ゴール

前提

  • VirtualBox での Linux を docker のホストにする。
  • データベースはホスト上の MariaDB を使う。

データベースエンジンは共通で構わなかったので、ホスト上にしています。

要件

  • ホスト上で WordPress 関連のファイルを編集できる。
  • ホスト上の WP-CLIwp コマンド)で制御できる。
  • PHP と WordPress の組み合わせを、任意に効率よく作成/起動/終了/破棄できる。

重要なのは、メモリ効率と自動化可能なこと。

ダメなもの

  • 効率が VCCW とさほど変わらないもの。
  • 作業ディレクトリの permission と owner の解決が難しいもの。
  • 各種操作や確認に docker コンテナに入る必要があるもの。

単純に docker を利用して稼働するだけの初歩的なサンプルでは、いろいろ躓くと思います。

説明

概念図

docker-compose を利用した WordPress の概念図

ブラウザからアクセスはリバースプロキシ jwilder/nginx-proxy:alpine を使って、動的なコンテナの追加/削除に対応させます。

データベースは socket ファイルをマウントして php.ini でパスを指定することで、ホスト上の MariaDB に繋げます。ホスト上でもコンテナ内でも localhost への socket 接続という形になるので、特別な工夫なしに、ホスト上の wp コマンドで各種操作が行えます。wordmove コマンドなども同様に稼働します。

使用ユーザー

www-data グループの www-data ユーザーで作業を行うことにします。あまりスマートな感じがしませんが、root で行うよりは無難です。

ホスト側にユーザやグループがなければ、コンテナで使われている uid (82) と gid (82) に合わせて作成しておきます。ついでに、sudodocker-compose コマンド等を実行できるように、wheel グループに追加しておきます。

sudo groupadd -g 82 www-data
sudo useradd -m -g www-data -u 82 www-data
sudo usermod -aG wheel www-data

ディレクトリ構成

説明上、次の要領で配置します。

~/docker/
  ├─ docker-compose.yml        # nginx-proxy
  ├─ nginx/
  │   ├─ default.conf          # for nginx service
  │   └─ proxy.conf            # for proxy service
  ├─ php/
  │   └─ mysql.ini             # for wordpress service
  ├─ wp53-php71/               # nginx and wordpress (PHP 7.1 + WordPress 5.3)
  ├─ wp53-php72/               # nginx and wordpress (PHP 7.2 + WordPress 5.3)
  └─ wp53-php73/               # nginx and wordpress (PHP 7.3 + WordPress 5.3)
      ├─ docker-compose.yml
      ├─ movefile.yml
      ├─ wp-cli.yml
      └─ html/

リバースプロキシ

jwilder/nginx-proxy を利用して、起動する各コンテナの VIRTUAL_HOST に応じて振り分けてもらいます。

コンテナ間の通信のために、あらかじめネットワーク wp_network を作っておきます。このネットワークに加えるのは、リバースプロキシと接続するコンテナだけです。

sudo docker network create wp_network

docker-compose.yml は次のように。phpmyadmin も含めています。

version: '3.3'

services:
  proxy:
    image: jwilder/nginx-proxy:alpine
    container_name: proxy
    restart: always
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./nginx/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin
    environment:
      PMA_ARBITRARY: 1
      PMA_HOST: localhost
      PMA_USER: root
      PMA_PASSWORD: ********
      VIRTUAL_HOST: phpmyadmin.test
    volumes:
      - /sessions
      - /run/mysqld/mysqld.sock:/run/mysqld/mysqld.sock
      - ./php/mysql.ini:/usr/local/etc/php/conf.d/mysql.ini:ro

networks:
  default:
    external:
      name: wp_network

./nginx/proxy.conf には、開発中のタイムアウト防止などの設定を書いておきます。

proxy_connect_timeout   300;
proxy_send_timeout      300;
proxy_read_timeout      90m;
send_timeout            300;
client_max_body_size  4096M;
proxy_buffers         8 32K;
proxy_buffer_size       32K;
proxy_busy_buffers_size 64K;

実際にブラウザでアクセスするには /etc/hosts 辺りに各コンテナの VIRTUAL_HOST を追加しておく必要があります。ここは仕方がなさそうです。(あるいは proxy.pac を利用して、ワイルドカード的に対応させるとか)

./php/mysql.ini には、マウントした socket ファイルのパスを設定しておきます。この設定は各コンテナでも使い回します。

mysqli.default_socket    = /run/mysqld/mysqld.sock
pdo_mysql.default_socket = /run/mysqld/mysqld.sock
max_execution_time       = 300
upload_max_filesize      = 4096M
memory_limit             = 4096M
post_max_size            = 4096M

WordPress の各コンテナ

ここでは Alpine な nginx と PHP-FPM で組みます。nginx がリバースプロキシ側と各コンテナのバーチャルホスト側で複数立つことになるのは妥協します。

さて、WordPress の docker のイメージには膨大なバリエーションのタグがあるのですが、fpm-alpine なものに限ると、リリース時期が異なるものがカバーされていません。

curl -s https://registry.hub.docker.com/v1/repositories/wordpress/tags | jq '.[].name' | grep fpm-alpine

ザッと眺めて表にすると、次のように。

WordPressPHP
5.67.07.17.27.37.4
4.8.0 ~ 4.9.0×××
4.9.1 ~ 5.0.2××
5.0.3 ~ 5.2.4×××
5.3.0 ~ 5.3.0××

WordPress 5.2 以降でも PHP 5.6 がサポートされているので、まだ簡単には切り捨てられません。

そこで、特定バージョンの WordPress が初期配置されていない wordpress:php5.6-fpm-alpinewordpress:php7.3-fpm-alpine を利用して、WordPress の初期配置は wp コマンドで行うことにします。

2012/12/12 追記。PHP 7.4 のイメージが加わっていました。

curl -s https://registry.hub.docker.com/v1/repositories/wordpress/tags | jq '.[].name' | grep php7.4-fpm-alpine
"5-php7.4-fpm-alpine"
"5.3-php7.4-fpm-alpine"
"5.3.0-php7.4-fpm-alpine"
"php7.4-fpm-alpine"

WordPress 5.3.0 初期配置済みと、初期配置なしのイメージですね。.env でのバージョン指定を PHP_VERSION=7.4 に変えれば試せます。

各コンテナの共通の設定

docker-compose.yml

各コンテナで共通の docker-compose.yml です。コピーで使い回します。

version: '3.3'

services:
  nginx:
    image: nginx:alpine
    restart: always
    volumes:
      - ./html:/var/www/html
      - ../nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    environment:
      VIRTUAL_ROOT: /var/www/html
      VIRTUAL_HOST: "${VIRTUAL_HOST}"
    networks:
      - wp_network
      - default

  wordpress:
    image: "wordpress:php${PHP_VERSION}-fpm-alpine"
    restart: always
    volumes:
      - /run/mysqld/mysqld.sock:/run/mysqld/mysqld.sock
      - ./html:/var/www/html
      - ../php/mysql.ini:/usr/local/etc/php/conf.d/mysql.ini

networks:
  wp_network:
    external: true

VIRTUAL_HOSTPHP_VERSION は個別に .env で定義します。

開発中のプラグインなどの配置は、html/ ディレクトリ配下にコピーを置くのが無難だと思います。マウントの場合 nginx と wordpress の両方にマウントするのが忘れがちになり、アンインストールまで含めてテストする場合、ミスると大元のファイルまで削除される事故に繋がります。ヒヤリとする事態は避けたいところです。

nginx の設定

nginx の設定も共通の ../nginx/default.conf をマウントします。

server {
    listen                     80;
    server_name                 _;
    root            /var/www/html;
    index               index.php;
    send_timeout              300;
    client_max_body_size    4096M;
    fastcgi_buffers         8 32K;
    fastcgi_buffer_size       32K;
    fastcgi_busy_buffers_size 64K;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $url =404;
        fastcgi_split_path_info ^(.+\.php)(\.+)$;
        fastcgi_pass wordpress:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

docker-compose の wordpress サービスには wp_network を追加していないので、各コンテナの nginx から見える wordpress:9000 は、docker-compose 単位の default ネットワーク内の wordpress サービスだけです。

各コンテナの個別の設定

.env
PHP_VERSION=7.3
VIRTUAL_HOST=wp53-php73.test

他の設定は wp-cli.yml へ。

wp-cli.yml

WP-CLI 用の設定ファイルです。詳細は Config – WP-CLI — WordPress.org 辺りを参照して書き換えてください。

path: html
url: http://wp53-php73.test
user: admin
color: true

core download:
  locale: ja
  version: 5.3

config create:
  dbname: wp5373
  dbuser: wordpress
  dbpass: *********
  dbprefix: wp_
  extra-php: |
    define( 'WP_DEBUG', true );

core install:
  title: WordPress 5.3 + PHP 7.3
  admin_user: admin
  admin_password: ********
  admin_email: test@example.com
  skip-email: true

コンテナ起動前に

wp core download
wp config create
wp db create
wp core install

を実行すると最低限のセットアップが完了した WordPress が準備できます。シェルスクリプト化しておいても良いでしょう。検証データの投入や自動テストもできたら最高ですね。

破棄するときは wp db drop などでドロップを忘れないようにしましょう。

まとめ

問い合わせなどでピンポイントな検証環境が急に欲しいときも、素早くローカルで準備できます。

仮想マシンとコンテナ技術は、似て異なります。うまく使い分けたいですね。

コメント

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