DockerでWordPressサイトを構築

概要

WordPressサイトをDockerで構築します。

サーバ構成は、Webサーバ3台+ロードバランサ、データベース2台(マスター/スレーブ)で少し拡張性を持たせた形にしました。

DockerはMacBook ProにDocker Desktopをインストールしました

設定

フォルダ構成

「docker_wordpress」フォルダを作成しその下に以下のファイルとフォルダを配置しています

docker_wordpress
├── docker-compose.yml
├── loadbalancer
│   └── nginx.conf #nginx設定ファイル
├── mysql
│   ├── Dockerfile-mysql
│   ├── db # データベースデータ(永続化)
│   │   ├── master 
│   │   └── slave
│   ├── log # データベースログ
│   │   └── master
│   │   └── slave
│   ├── master
│   │   ├── conf.d
│   │   │   └── mysql_master.cnf #データベース設定ファイル(マスター)
│   │   └── initdb.d
│   │       └── master.sh # データベース初期設定スクリプト(スレーブ)
│   └── slave
│       ├── conf.d
│       │   └── mysql_slave.cnf #データベース設定ファイル(スレーブ)
│       └── initdb.d
│           └── slave.sh # データベース初期設定スクリプトファイル(スレーブ)
└── web
    ├── Dockerfile-web
    └── wordpress # wordpressファイルの格納フォルダ

docker-compose.yml

まずはdocker-compose.ymlを作成します。

データベースサーバ(MySQL)、webサーバ(apache)、ロードバランサー(nginx)を設定します

depends_on

起動順番をdepends_onを使って以下に設定しています

  1. データベースサーバ(マスター)
  2. データベースサーバ(スレーブ)
  3. Webサーバ(apache)
  4. ロードバランサー(nginx)

version: "3"

services:
  mysql-master: # マスターデータベース
    image: mysql:5.7
    restart: always
    volumes: 
      - ./mysql/log/master:/var/log/mysql # データベースデータ(永続化)
      - ./mysql/db/master:/var/lib/mysql # データベースログ
      - ./mysql/master/conf.d/:/etc/mysql/conf.d # データベース設定ファイル
      - ./mysql/master/initdb.d:/docker-entrypoint-initdb.d # 初期スクリプトファイル
    tty: true
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: root_db_pass
      MYSQL_DATABASE: wordpress_db
      MYSQL_USER: wordpress_db_user
      MYSQL_PASSWORD: wordpress_db_pass
    build:
      context: .
      dockerfile: ./mysql/Dockerfile-mysql

  mysql-slave: # スレーブデータベース
    depends_on:
      - mysql-master # マスターデータベースの処理が完了してから開始
    image: mysql:5.7
    restart: always
    volumes:
      - ./mysql/db/slave:/var/lib/mysql # データベースデータ(永続化)
      - ./mysql/log/slave:/var/log/mysql # データベースログ
      - ./mysql/slave/conf.d:/etc/mysql/conf.d # データベース設定ファイル
      - ./mysql/slave/initdb.d/:/docker-entrypoint-initdb.d # 初期スクリプトファイル
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: root_db_pass
      MASTER_MYSQL_HOST: mysql-master
      MASTER_MYSQL_USER: wordpress_db_user
      MASTER_MYSQL_PASSWORD: wordpress_db_pass
    build:
      context: .
      dockerfile: ./mysql/Dockerfile-mysql

  web:  # Webサーバ
    depends_on:
      - mysql-slave
    image: wordpress:php7.4-apache
    deploy:
      replicas: 3 #web 3台
      resources:
        limits:
          cpus: "0.2" # CPU
          memory: 100M # メモリ
      restart_policy:
        condition: on-failure
    volumes: # dockerコンテナとmacフォルダを同期
      - ./web/wordpress:/var/www/html #wordpressファイル
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_USER: wordpress_db_user
      WORDPRESS_DB_PASSWORD: wordpress_db_pass
    build:
      context: .
      dockerfile: ./web/Dockerfile-web

  nginx_server:  # ロードバランサー
    depends_on:
      - web # Webサーバの処理が完了してから開始
    image: nginx
    links:
    - web
    volumes:
    - ./loadbalancer:/etc/nginx/conf.d #nginx設定ファイル
    ports:
    - "80:80"

ロードバランサー(nginx)設定

./loadbalancer/nginx.conf

upstream

負荷分散させるwebサーバのコンテナ名を登録します

upstream web {
    server docker_wordpress_web_1;
    server docker_wordpress_web_2;
    server docker_wordpress_web_3;
}

server {
    listen       80;
    location / {
           proxy_pass http://web;
    }
}

データベース(MySQL)設定

./mysql/Dockerfile-mysql

upstream

vimをデバッグ用にインストールしておきます

FROM mysql:5.7

RUN ["apt", "update"]
RUN ["apt", "install", "-y", "locales"]
RUN ["locale-gen", "ja_JP.UTF-8"]
RUN ["apt", "install", "-y", "vim"]

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja

./mysql/master/conf.d/mysql_master.cnf

mysqld

レプリケーションを有効にするためlog-binとserver-idを設定します

server-idはスレーブ側と被らなければOKです。

[mysqld]
log-bin
server-id=1
gtid-mode=ON
enforce-gtid-consistency=ON
general_log=ON #クエリログが有効
general_log_file=/var/log/mysql/query.log #ログファイルのパース

./mysql/slave/conf.d/mysql_slave.cnf

mysqld

server-idはマスター側の被らないようにします。

読み込み専用としてread_onlyも設定しておきます。

[mysqld]
server-id=2
read_only
gtid-mode=ON
enforce-gtid-consistency=ON
general_log=ON #クエリログが有効
general_log_file=/var/log/mysql/query.log #ログファイルのパース

./mysql/master/initdb.d/master.sh

GRANT REPLICATION

MYSQL_USER(wordpress_db_user)にレプリケーション権限を付与します。

#!/bin/sh
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e"GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_USER'@'%';"
chmod

スクリプトに実行権限を付与します(付与しないと起動時に実行されないので忘れずに)

$ chmod a+x ./mysql/master/initdb.d/master.sh

./mysql/slave/initdb.d/slave.sh

CHANGE MASTER

スレーブ側でマスターデータベースサーバの設定を行いスレーブスタートします

#!/bin/sh
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e" \
    CHANGE MASTER TO \
        MASTER_HOST = '$MASTER_MYSQL_HOST', \
        MASTER_PORT = 3306, \
        MASTER_USER = '$MASTER_MYSQL_USER', \
        MASTER_PASSWORD = '$MASTER_MYSQL_PASSWORD', \
        MASTER_AUTO_POSITION = 0; \
    START SLAVE; \
"
chmod

スクリプトに実行権限を付与します(付与しないと起動時に実行されないので忘れずに)

$ chmod a+x ./mysql/slave/initdb.d/slave.sh

Webサーバ(Apache)設定

./web/Dockerfile-web

apt-get

デバッグ用にvimをインストールします

FROM wordpress:php7.4-apache

RUN ["apt", "update"]
RUN ["apt", "install", "-y", "vim"]

WordPress設定

ダウンロード

WordPressをダウンロードして「./web/wordpress/」フォルダに入れます

./web/wordpress/wp-config.php

wp-config.php

WordPressにデータベースやホスト情報などを設定します

/** WordPress のためのデータベース名 */
define('DB_NAME', 'wordpress_db');

/** MySQL データベースのユーザー名 */
define('DB_USER', 'wordpress_db_user');

/** MySQL データベースのパスワード */
define('DB_PASSWORD', 'wordpress_db_pass');

/** MySQL のホスト名 */
define('DB_HOST', 'mysql-master');
define('DB_HOST_RO', 'mysql-slave');

/** ドメイン設定 */
define( 'WP_HOME', 'http://localhost' );
define( 'WP_SITEURL', 'http://localhost' );

/**認証用ユニークキー
 * それぞれを異なるユニーク (一意) な文字列に変更してください。
 * {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org の秘密鍵サービス} で自動生成することもできます。
 * ↓必ず変更してください
 */
define('AUTH_KEY',         'xl@j9?C%C0#;7n)|<( bZ75qPlME?I|+!E=b_JeC|hQc*<e=Roh&$h{cDni(7*)Y');
define('SECURE_AUTH_KEY',  '~UcxG46u|-+<6g:Im}^ydPsQ3|,X]FBcf-S9*)Z2Tu`[S|Zvi,y`F!am&NGY2QC%');
define('LOGGED_IN_KEY',    'OL>v:TV8}ly<N(pY5-|-!I3z3Orw~cW.q|~Xb9,n&GK=L^_Djse5AfRQLv-;|4nv');
define('NONCE_KEY',        '&Q>P!:3}z@DBo 6w 3Uv&R=NQ8;6S(OKl.:Up5-MXc+;_^-dU>}nt-K/AzdCEz<)');
define('AUTH_SALT',        'f]>5SzqN+.gd*[cea|CZ_:nR|+i3l^RI/q_hs&Dnrg*R$|1H:_b-izl,ERs*_?#g');
define('SECURE_AUTH_SALT', '<zV}MZnr* 2f2:mwAMIe*o-eF%SJ^z`$W!T.va0+!p0F=^Rxb|Ef-msDr;6yZJv!');
define('LOGGED_IN_SALT',   'T:x`Jq_PLbchkig5D._jn>7,af !gbB]`U ;pZMVYztF59R>N4WO&X$U0}^v^Q}*');
define('NONCE_SALT',       '6%L]i|}N!c  x;q6$ULl5_my[0^0,aUI3^7lVUD(MR)B]NAHv!Bt24wy1-hE#sV,');

起動

wp-config.php

すべての設定が完了したのでdocker-composeで起動します

$ docker-compose up -d --build

オプション
-d:コンテナをバックグラウンドで起動します(同じターミナルで作業を継続できます)
--build:Dockerfile変更を反映

WordPressの動作確認

初期画面
wordpress_初期画面

ブラウザでhttp://localhostと入力し、WordPressの初期画面が表示されれば成功

そのまま初期設定を行います

サイトトップ画面
wordpress_トップ

再度、ブラウザでhttp://localhost/と入力してサイトトップが表示されることを確認します

ダッシュボード画面
wordpress_ダッシュボード

また、ブラウザでhttp://localhost/wp-admin/と入力し、ログイン後にダッシュボードも表示されることも確認します

コンテナ起動確認

docker ps

dockerコンテナの確認を行います。

nginx、webサーバ3個、データベースサーバ2個のSTATUSが「UP」になっていることを確認します

$ docker ps -sa --format "table {{.Image}}\t{{.Names}}\t{{.Status}}"

IMAGE                     NAMES                             STATUS
nginx                     docker_wordpress_nginx_server_1   Up About an hour
wordpress:php7.4-apache   docker_wordpress_web_2            Up About an hour
wordpress:php7.4-apache   docker_wordpress_web_1            Up About an hour
wordpress:php7.4-apache   docker_wordpress_web_3            Up About an hour
mysql:5.7                 docker_wordpress_mysql-slave_1    Up About an hour
mysql:5.7                 docker_wordpress_mysql-master_1   Up About an hour

データベースのレプリケーション確認

show master status;

マスターデータベースとスレーブデータベースの状態を確認します

FileとPositionが設定されていることを確認します

マスターデータベース
$ docker exec -it docker_wordpress_mysql-master_1 bash
root@5596c918f946:/# root@5596c918f946:/# mysql -u root -proot_db_pass
mysql> show master status;
show master status
show master status
スレーブデータベース
show slave status¥G

スレーブ側の動作状況を確認します

「Master_Log_File」と「Read_Master_Log_Pos」がマスター側と一致して、Slave_IO_RunningとSlave_SQL_Runningが両方ともYesになっていれば正常にレプリケーションされています

$ docker exec -it docker_wordpress_mysql-slave_1 bash
root@5596c918f946:/# root@5596c918f946:/# mysql -u root -proot_db_pass
mysql> show slave status¥G

          Master_Host: mysql-master            ← マスターデータベースのホスト
          Master_User: wordpress_db_user       ← マスターデータベースのユーザ
          Master_Port: 3306
      Master_Log_File: 5596c918f946-bin.000001 ← マスターのFileと一致  
  Read_Master_Log_Pos: 154                                           ← マスターのPosisonと一致
     Slave_IO_Running: Yes                     ← Yesになっていること
    Slave_SQL_Running: Yes                     ← Yesになっていること

WordPressのデータベースレプリケーション設定

HyperDB

初期状態のWordPressはデータベースサーバを一つしか指定できません。(wp-config.phpで設定)

そのため、いまの状態はデータベースはレプリケーションされてますがクエリはすべてマスターデータベースで処理されています。

今回はプラグイン「HyperDB」を使ってWordPressのレプリケーション設定をします。

HyperDB設定

WordPressのダッシュボード(プラグイン)からHyperDBをインストール&有効化

新規プラグイン

プラグイン画面でHyperDB」と検索

HyperDBをインストール

HyperDBをインストール

HyperDBを有効化

HyperDB有効化

./web/wordpress/db-config.php設定

db-config.php

インストールが終わったらPHP側を修正します。

db-config.phpをwp-config.phpと同じ階層に配置します。

インストールが終わったらPHP側を修正します。

db-config.phpをwp-config.phpと同じ階層に配置します。

<?php
// Master ( read and write )
$wpdb->add_database(array(
        'host'     => DB_HOST, // マスターデータベースのホスト
        'user'     => DB_USER,
        'password' => DB_PASSWORD,
        'name'     => DB_NAME,
        'write'    => 1, // 1は書き込み有効
        'read'     => 1, // 1は読み込み有効
));

// Slave ( read only )
$wpdb->add_database(array(
        'host'     => DB_HOST_RO, // スレーブデータベースのホスト
        'user'     => DB_USER,
        'password' => DB_PASSWORD,
        'name'     => DB_NAME,
        'write'    => 0, // 0は書き込み無効
        'read'     => 1, // 1は読み込み有効
));

db.phpファイルコピー

db.php

したhyperdbに含まれるdb.phpをwp-content配下にコピーします

インストールしたhyperdbに含まれるdb.phpをwp-content配下にコピーします

$ cp ./web/wordpress/wp-content/plugins/hyperdb/db.php ./web/wordpress/wp-content/

レプリケーションの動作確認

マスターのクエリログ

query.log

サイトにアクセスし更新系、データ取得系の両方が処理されていることを確認します

$ tail -100f ./mysql/log/master/query.log

更新系、データ取得系の両方が処理されます

スレーブのクエリログ

query.log

データ取得系のみが処理されていることを確認します

$ tail -100f ./mysql/log/slave/query.log

データ取得系のみ処理されます

コメント

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