8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WP-CLI+WordPress+DB+データ専用コンテナをdocker composeで|ローカル環境構築ハンズオン

Last updated at Posted at 2022-04-05

前提

WordPressサイトのオリジナルテーマ作成運用、プラグイン開発運用などに使用している環境になります。WordPressはドメインを投稿時の画像URLなどに書き込む特性があるのでドメインもローカルで同じものが使えるように設定します。こうすることで自動デプロイがやりやすくなります。DBは本番から手動エクスポートしてダウンロードしDBの同期はしていません。(個人的には必要な時にダウンロードする形であまり困ったことはありません。)

なお今回作成するサイトのドメインはexample.comとして進めていきますが
適宜、皆様の環境に合わせて変えてみてください。
このドメインに関しては本番用としてドメインレジストラから取得しているもの
架空で設定するものなど好きに設定しても大丈夫です。
※このあたりよくわからない方は実在しないであろう乱数字的なドメインを
設定すればどこかに影響が出る可能性を下げられるため安心かと思います。
例)weoriuewqryoiuv6786234kiuywerkhjqwerhiasudyfqweryui197j.com

この環境を使うことで感じているメリット

Docker,Linux,nginx,apacheなどのサーバ関連の勉強になります。
いわゆるバーチャルマシン環境よりかなりデータ量も軽量で立ち上がりも早いです。(控えめにいっても体感で数倍は違います)
Docker,Linux,nginx,apacheなどのサーバ関連デファクトスタンダードな環境で開発ができます。
デファクトスタンダードなので共有できる知見を持っている人も多いです。

以下はlocalというツールでも簡単にできるものです。
とりあえず簡単にローカル環境を構築したいという方はlocalをお勧めします。
サーバ環境をより知りたい方はDockerもお勧めです。

PHPやMySQLのバージョンを変えて気軽にテストができます。
プラグイン、WordPressのバージョン違いのテスト、バージョンアップ&ダウンが簡単にできます。
チーム開発する際などに同じ環境を簡単に共有、再現することができます。

予想されるデメリット

Docker,Linux,nginx,apacheなどのサーバ関連の知識が必要になるので
コーダーの方やデザイナーの方は導入する際の学習コストは高めかもしれません。
それゆえ前提知識がないとブラックボックス化するのでトラブルがあった際にはまります。

コンテナ構成(ローカル環境)

nginxプロキシ(このコンテナだけ1つ作成して複数サイト間で使いまわしています)

WP-CLIコンテナ
WordPressコンテナ

MySQLコンテナ

データ専用コンテナ

WP-CLIコンテナ以下はサイトごとにこのような構成をそれぞれ作っています。これは現在運用中のサイトが複数あり、使っているプラグインが違っていたり、WordPressのコアバージョンが違っていたりするのでその辺りの検証を個別にできるようにするために分けています。今回の構成からもう少し抽象度を上げて組めばURLだけ変えたらサイトを切り替えるなんてこともできそうですがそれをやったらやったで運用上混乱が起きる(環境どうしの蜜結合が起こってくる)と思うので現在の構成にしています。

運用環境構成

ローカル環境(今回はここのみ、MacOS前提で進めます)

GitHub
GitHubAction

本番サーバ

nginxプロキシコンテナ設定ファイルの作成

プロキシサーバとはその名の通り代理でブラウザの代わりにサーバ(ここではWordPressコンテナ)にアクセスしてくれるという役割を担っています。

ここではブラウザからのアクセスを一旦プロキシに送るようにします。それにはローカルPC(ホストOS)のhostsファイル(/private/etc/hosts)を編集します。これによって普段example.comにアクセスしたらexample.comの本番サーバに通信されるのをローカルPC内のnginxプロキシに向けられるようになります。
以下をhostsファイルの最下部に追記します。

0.0.0.0 example.com

これで保存をしてexample.comにアクセスするとローカルPC内のプロキシを見に行くようになります。
元のようにように本番に見にいくようにするには上記の行をコメントアウトして保存します。

# 0.0.0.0 example.com

それではまずプロキシコンテナを格納するディレクトリを好きな名前で任意の場所に作成します。
そしてディレクトリ直下に以下のファイルを作成します。

docker-compose.yml

version: "3.7"
services:
  proxy:
    image: jwilder/nginx-proxy
    container_name: proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./nginx:/etc/nginx
      - ./certs:/etc/nginx/certs:ro
    restart: always
    logging:
      options:
        max-size: 5m
        max-file: "10"
volumes:
  shared-volume:
    name: shared
networks:
  default:
    name: shared

ymlについての詳細は以下の記事をご参照ください。

これでプロキシコンテナの設定は完了です。

WP-CLI,WordPress,MySQLコンテナ設定ファイルの作成

まずはサイトのローカル環境を格納するディレクトリを好きな名前で任意の場所に作成します。
そしてディレクトリ直下に以下のファイルを作成します。

docker-compose.yml

version: "3.7"
services:

  wpcli:
    image: wordpress:cli
    container_name: wpcli
    volumes:
      - example-wp:/var/www/html
      - ./tmp:/tmp
    command: chown xfs:xfs /tmp/wpcli-entrypoint.sh &&
             sh /tmp/wpcli-entrypoint.sh mysql exampleuser examplepass
    user: root
    networks:
      - default
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: wordpress

  mysql:
    platform: linux/x86_64
    image: mysql:5.7.37
    volumes:
      - example-dbdatavolume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
    restart: always
    networks:
      - default
    logging:
      options:
        max-size: 5m
        max-file: "10"

  wordpressimage:
    image: wordpress:latest
    volumes:
      - example-wp:/var/www/html #デフォルトで作成されるvolumeをわかりやすくするための設定
      - ./tmp:/tmp
      - ./etc/vhost-example.conf:/etc/apache2/conf.d/vhost-example.conf
      - ./etcphp/php.ini:/usr/local/etc/php/php.ini
      - ./wp-content:/var/www/html/wp-content
    container_name: example-wp-ct
    environment:
      VIRTUAL_HOST: example.com
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: wordpress
      CERT_NAME: default
    depends_on:
      mysql:
        condition: service_started
    restart: always
    tty: true
    networks:
      - default
    logging:
      options:
        max-size: 5m
        max-file: "10"

volumes:
  example-wp:
  example-dbdatavolume:
    external: true #事前にデータ専用コンテナを作成(compose管理外のコンテナを探す指定)

networks:
  default:
    name: shared

#volumeの構成
#shared用に1つ、これは複数サイト共用。
#wp用に1つ。サイトごとに1つ生成される。
#データ専用コンテナ1つ。サイトごとに1つ生成。

少し長いですが基本的にはプロキシで指定していたのと同じくdocker-compose.ymlでの設定です。
やっていることとしては
WP-CLI(Wordpressのバージョンアップダウン、プラグインのバージョンアップダウンなどがコマンドで簡単にできるツール)
Wordpress本体
MySQLサーバ
のコンテナを一気に順番を制御して立ち上げています。
順番に関しては以下のような理由があります。
MySQLが一番立ち上がるのに時間がかかります。
WP-CLIでWordPressのインストールを実行するのにMySQLが立ち上がっていないとエラーになります。
これらの理由から順番を制御する必要があります。詳細は後述するtmpディレクトリの項でシェルスクリプトを作成しているのでそちらをご参照ください。

ここのdocker-compose.ymlではプロキシでは使っていなかった項目があるので少し補足していきます。

WordPressコンテナ

wordpressimage:
この要素ではWordPressコンテナを作成しています。

volumes要素

volumes:
    - example-wp:/var/www/html #デフォルトで作成されるvolumeをわかりやすくするための設定
    - ./tmp:/tmp
    - ./etc/vhost-example.conf:/etc/apache2/conf.d/vhost-example.conf
    - ./etcphp/php.ini:/usr/local/etc/php/php.ini
    - ./wp-content:/var/www/html/wp-content

volumesというのはDockerがファイル管理をする際に使用する仕組みのことです。
主にはデータを保持するためにホストOS(ローカルPCのOS自分の場合はMacOS)のディレクトリに
Dockerからデータを保存したり、逆にホストOSから読み込んだりしています。

volumeはコンテナを生成したら一緒に作成されここでは
exapmle-wpという名前をつけてvolumeを生成しています。
(名前をつけないと乱数時で生成されるので個人的には管理しやすくするため名前をつけています)
/var/www/htmlはDockerコンテナ内のパスでこのディレクトリをまるっとホストに持ってきて保存します。
exapmle-wpというvolumeがホストOS内にあれば2回目からはそのホストOS内のディレクトリを
コンテナ内に読み込んで使用するというイメージです。
これはいわゆるVolumeと言われるマウントのやり方になります。

./tmp:/tmp以下の3つも基本的には同じくホストOSにディレクトリを作って
その中のファイルをDocker内に読み込むということをしています。
こうすることでコンテナを削除したりしてもデータはホストOS側にあるので消えなくなります。
そしてこの3つはバインドマウント(short syntax)という手法になります。
VolumeマウントではDockerが自動的にホストOS内にディレクトリを作成していますが
バインドマウントではユーザーが自分でディレクトリを作成して管理します。
今回はymlファイルと同階層にtmp,etc,etcphp,wp-contentのディレクトリを配置しています。

tmpディレクトリ

ここにはシェルスクリプトのファイルを置きます。
そしてDockerコンテナを立ち上げた時に実行してWP-CLIコマンドを使って
WordPressのインストール作業を自動化しています。

etcディレクトリ

ここにはapacheで使用するバーチャルホストのファイルを指定しています。
バーチャルホストを使用することで指定のドメインでapache経由で指定のディレクトリを表示することができます。

etcphpディレクトリ

こちらはphpのXdebugを使用する際にphp.iniファイルを編集する必要があったので設置しています。
あとWordPressのファイルアップロードのデータ上限を2Mより上げたい場合もphp.iniファイルで設定できます。
必要なければ削除しても良いと思います。

wp-content

WordPressのディレクトリですね。プラグイン、テーマ、アップロードファイルなどが格納されています。私のケースではプラグイン、テーマを開発しているのでまるっとバインドマウントしています。gitもこのディレクトリ以下で管理しています。人によってはプラグインディレクトリだけ、テーマディレクトリだけというのもあるかもしれません。

environment要素

environmentは環境変数です。環境変数とは
ざっくりいうとサーバ内で使える変数というイメージです。

environment:
    VIRTUAL_HOST: example.com
    WORDPRESS_DB_HOST: mysql
    WORDPRESS_DB_USER: exampleuser
    WORDPRESS_DB_PASSWORD: examplepass
    WORDPRESS_DB_NAME: wordpress
    CERT_NAME: default

VIRTUAL_HOST

今回のプロジェクトのURLを指定します。
これは前述のプロキシサーバが読みにきます。

WORDPRESS_DB_HOST

DBサーバのホスト名を設定します。

WORDPRESS_DB_USER

DBのユーザー名を設定します。

WORDPRESS_DB_PASSWORD

DBのパスワードを設定します。

WORDPRESS_DB_NAME

DBの名前を設定します。

WORDPRESS_DBとついているものはwordpress公式イメージで設定されている変数です。

CERT_NAME

SSL証明書の設定

network要素

これは一番上の階層のnetwork要素のdefault、つまりsharedという名前のネットワークの中に所属しますよという指定です。
Dockerコンテナは基本的に同じネットワーク内のコンテナは自動で繋がるようになり、後述するWP-CLI,MySQLコンテナも
同じネットワークにすることで通信ができるようになります。

networks:
    - default

WP-CLIコンテナ

wpcli:
この要素ではWP-CLIコンテナを作成しています。

volumes要素

volumes:
    - example-wp:/var/www/html

example-wpというのはWordPressコンテナで指定していたvolumeです。
これはホストOS上に作成されたvolumeディレクトリ(example-wp)を
WP-CLIコンテナ内の/var/www/htmlに呼び込んで使用するという意味になります。
つまり一つのホストOS上のディレクトリを2つのコンテナで共有していることになります。
ここではhtml直下にWordPressのファイルが展開されています。
そしてWP-CLIではインストール時にwp-config.phpなどを生成したり
そこにDBの情報を書き込んだりしてセットアップをコマンドラインから行うことができます。

tmpディレクトリ

- ./tmp:/tmp

tmpディレクトリには自分で作成するシェルスクリプトを設置します。
ここでは以下のシェルを置きます。

#!/bin/ash

set -e

host="$1"
shift
user="$1"
shift
password="$1"
shift
cmd="$@"

echo "Waiting for mysql"
until mysql -h"$host" -u"$user" -p"$password" &> /dev/null
do
       >&2 echo -n "."
       sleep 1
done

>&2 echo "MySQL is up - executing command"
#ここまでがmysqlコンテナが立ち上がるのを待つためのスクリプト

if [ ! -e '/check' ]; then
    touch /check
    cd /var/www/html
    rm /var/www/html/wp-config.php
    wp config create --allow-root --dbname=wordpress --dbuser=exampleuser --dbpass=examplepass --dbhost=mysql --dbprefix=wp_
    sed -i -e "98a \$_SERVER['HTTPS'] = 'on';" wp-config.php
    chown www-data:www-data /var/www/html/wp-config.php
    wp core install --allow-root --url="example.com" --title="example-title" --admin_user="xxxxxxxxxxxxxxx" --admin_password="xxxxxxxxxxxxxxxxxx" --admin_email="example-docker@gmail.com" --path="/var/www/html"
    wp rewrite structure --allow-root "%postname%" --url="example.com" --path="/var/www/html"
    chown -R www-data:www-data /var/www/html/wp-content/
    wp option update --allow-root home 'https://example.com'
    wp option update --allow-root siteurl 'https://example.com'
    tail -f /var/log/serverlog
else
    # 2回目以降
    tailf /var/log/serverlog
fi

ざっくり流れを説明しますと
最初の行から
&2 echo "MySQL is up - executing command"の行までが
MySQLコンテナが立ち上がるのを待つためのスクリプトになります。
MySQLコンテナが立ち上がらない状態でWordPressのインストールなどを
WP-CLIで実行するとWordPressコンテナからMySQLコンテナを操作しようとするためエラーになります。

そのあとは初回(WordPressが設定されていない状態)のみ
WordPressの設定をするということになります。
これはいわゆる最初ブラウザからインストールの設定をすると思いますが
あの作業をWP-CLIを使ってコマンドから自動化しています。
そのほかにもwp-config.phpにするHTTPSの設定、
パーマリンクの変更などを行っています。

前述のシェルスクリプトをコピペする際はドメイン、admin_user、admin_passwordなどを適宜変えてご使用ください。

command要素

コマンド要素ではdocker起動時に実行するコマンドを以下のように
コマンド形式、シェルスクリプトファイルを指定して実行できます。

command: chown xfs:xfs /tmp/wpcli-entrypoint.sh &&
         sh /tmp/wpcli-entrypoint.sh mysql exampleuser examplepass

まずバインドマウントしたシェルスクリプトファイルのパーミッションを
WordPressコンテナのwpルート以下の実行ユーザーwww-dataに合わせています。
WordPressコンテナのディストリビューションはDebianでユーザーwww-dataはuid、gid共に33です。
一方WP-CLIコンテナのディストリビューションはAlpineでユーザーxfsがuid、gid共に33です。
パーミッションを合わせてから前述のシェルスクリプトを実行しています。
mysql exampleuser examplepassはシェルスクリプトに渡している値で
シェルスクリプト内に読み込まれて変数に代入されて使用されます。

user要素

こちらはWP-CLIコンテナ内のディストリビューションAlpine Linuxを
どのユーザーで実行するかを指定しており、この記述でxfsで実行するようになります。

user: xfs

networks要素

これはWordPressコンテナで説明したのと同じ指定です。
所属するネットワークを指定しています。

networks:
    - default

environment要素

こちらもWordPressコンテナで指定したものと同じです。
WP-CLIでMySQLを操作することもあるので必要になります。

    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: wordpress

MySQLコンテナ

mysql:
ここではMySQLコンテナを作成しています。

platform要素

platform要素はM1チップを使用しているMacで必要になります。
CPUがintelの場合は削除します。

    platform: linux/x86_64

volumes

ここで指定しているのは後述するデータ専用コンテナのvolumeになります。まだvolume自体ない状態です。
このようにデータベースコンテナとデータを格納するコンテナ(データ専用コンテナ)を分けることで
データベースのバージョン違いのテストやデータベース自体を変更してのテストなどがやりやすくなります。

volumes:
    - example-dbdatavolume:/var/lib/mysql

データ専用コンテナ

データ専用コンテナはbusyboxという軽量のコマンド集、ソフトウェアとのことでした。
以下のコマンドでコンテナが立ち上がり同時にコンテナ内に入った状態になります。
このコマンドを実行することでexample-dbdatavolumeというvolumeも作成されます。

docker run -i -t --name example-dbdatacontainer --mount source=example-dbdatavolume,target=/var/lib/mysql busybox

余談ですがls -laコマンドでルートのディレクトリ構成を見てみるとLinuxとほぼ同じような構成になっています。
ここではコンテナ内で特にやることはないので以下のコマンドでコンテナを抜けます。

exit

ここまで設定できたら準備完了です。

コンテナ立ち上げ

それではコンテナを立ち上げましょう。

プロキシコンテナ立ち上げ

まずはターミナルを立ち上げホストOS上でプロキシコンテナ用に作成したディレクトリに移動します。
そして以下のコマンドでコンテナを立ち上げます。

docker compose up -d

これでプロキシサーバが立ち上がりました。

CLI+アプリ+DBコンテナ立ち上げ

次にローカル環境として作成したディレクトリに移動して以下のコマンドを実行します。

docker compose up -d

これでCLI+アプリ+DBコンテナが立ち上がりました。
データ専用コンテナはExited状態になっていると思いますがこれで機能してくれます。

ブラウザからアクセス

前半設定したhostsファイルの設定を確認して
example.comなど設定したアドレスでブラウザにアクセスしてみます。
証明書の警告が出ますが今回は自分で作成した環境(0.0.0.0)にアクセスしているので
そのままアクセスするリンク(ボタンやリンクなどを押さないと出てきません)をクリックします。
これでWordPressが表示されれば完了です。

管理画面に入るには

example.com/wp-adminにアクセスします。
ユーザー名、パスワードはシェルスクリプトの
wp core installの行で指定したもので入れます。

似たサイトを複数立ち上げる場合|プラグインインストールなども自動化

今回の手順通り進めるとホストOSのローカル環境として作成したディレクトリに
wp-contentディレクトリが自動的に作成されていると思います。
これはWordPressコンテナの以下の行

    - ./wp-content:/var/www/html/wp-content

でこのように指定されているため
ホストOS上にディレクトリがない場合はコンテナ内のディレクトリを
ホストOS上にコピーしてくれます。
つまりWordPress初期で設定されるwp-contentディレクトリがコピーされます。

ただいつも使うプラグインやベースとなるテーマがある場合は
wp-contentディレクトリをあらかじめホストOS上に置いておくと
逆にホストOSからdockerコンテナ内にコピーしてくれます。

するとプラグインのダウンロードなどもスキップできます。
WP-CLIのシェルスクリプトにコマンドを足せば
プラグインアップデートなどを自動化することも可能です。

dockerコンテナが立ち上がらない場合

コンテナが立ち上がらなくなる場合も結構あります。
原因は様々ですがまずは立ち上げ方を変えるとプロセスが見えるようになります。

docker compose up

オプションdを外すとバックグラウンドではなくログがリアルタイムで
表示されるようになるので結構便利です。

ターミナルで新しいタブをひらけばdockerコマンドも普通に使えます。

環境を共有したい場合

基本的には今回作成した2つのディレクトリ
プロキシのディレクトリと
CLI+WP+DBのディレクトリをコピーして
別PCに移動してdocker compose up
データ専用コンテナも同じようにdocker runで作成すれば共有できると思います。

後書き

最近M1Macを導入したこともあり環境を見直してみたところ
WP-CLIコンテナも組み込むことができたのでまとめてみました。
(以前は自分でシェルスクリプトをねじこんでました)
使い方が間違っている部分、わかりづらい部分、もっと効率化できそうな部分などは
ご指摘いただけたら嬉しいです。

私がこの環境を導入している一番のモチベーションはサーバ環境の知識を勉強するというのが一番かもしれません。導入時に簡易ツール(MAMPやLocal)なども少し調査しましたが、当時MySQLのバージョンが変えられなかったり、SQL言語が固定だったりというところがありました。この辺はツールも進化していくのでそれを待てるかどうかは個々人の好みだと思います。個人的な経験としてMySQLのバージョンが上がった際、某レンタルサーバがMariaDBを採用した際、構築時にShellScriptで自動化する際などは今回の構成で獲得できた知識が活きたなと感じています。ともかく低レイヤーに行くほど自由度は上がるという法則はありますのでお好みでやり方やツールを選ぶのが良いと思います。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?