AWS EC2上でDockerを使って複数のWordPressを動かす

AWSにWordPressを移行する 計画編の続きです。今回はEC2上でDockerを使ってWordPressを構築します。

Dockerについて

Dockerのコンテナは起動している間は変更したデータは残りますが、コンテナを消去すると失われますし、外部に持ち出すことができません。永続化したい変更はホスト内のディレクトリやファイルをbind mountするか、Dockerfileを使ってbuild時に適用する必要があります。

EC2にDockerをインストール

インスタンスにSSH接続し、以下のコマンドでDockerをセットアップします。ec2-userでdockerが実行できるようにdockerグループに追加しています。

sudo amazon-linux-extras install docker
sudo service docker start
sudo usermod -a -G docker ec2-user

docker-composeをインストールします。docker-composeを使うことで、dockerコンテナのビルドや起動が簡単になります。

sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

よく使うコマンド

docker-compose up -d
docker-compose.yamlのコンテナをまとめて起動するコマンドです。-dでバックグラウンドで起動します。

docker-compose stop
コンテナを停止するコマンドです。

docker-compose down
コンテナを停止して、消去します。

docker ps
実行中のコンテナを表示

docker-compose logs(docker logs コンテナ名)
コンテナのログを表示

docker system prune
使用していないコンテナやイメージの消去

サービスの構成

2つのWordPressで1つのMySQLを共有します。リバースプロキシで各WordPressへの接続を振り分けます。dockerにはjwilder/nginx-proxyというほぼ設定なしでnginxでリバースプロキシを建てれるイメージがあります。データベース管理用にphpMyAdminも入れておきます。VPSにdockerで複数サイトをホスティングするには?を参考に、共有サービス、2つのWordPressをそれぞれ別のディレクトリに作成していきます。

EC2のセキュリティグループの設定からポート80、443、8000(phpMyAdmin用)を解放しておきます。80、443はソースを任意の場所、8000はマイIPにするか、必要なくなったら閉じておきましょう。

共有サービス(nginx-proxy,MySQL,phpMyAdmin)のセットアップ

sharedディレクトリに以下のdocker-compose.ymlを設置し、docker-compose up -dで起動します。

version: '3'

services:
   nginx:
      container_name: nginx_proxy
      image: jwilder/nginx-proxy
      ports:
        - 80:80
        - 443:443
      volumes:
        - /var/run/docker.sock:/tmp/docker.sock:ro
        # - ../lego/lego/certificates:/etc/nginx/certs
      restart: always
      logging:
        options:
          max-size: 5m
          max-file: "10"

   db:
     image: mysql:5.7
     volumes:
       - ./mysql/data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: root_pass
       MYSQL_DATABASE: wordpress_1
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress_pass

   phpmyadmin:
     image: phpmyadmin/phpmyadmin:latest
     restart: always
     ports:
       - 8000:80

nginx-proxy

docker.sockをbind mountしておくことで、VIRTUAL_HOSTが設定されたコンテナの起動を感知して、自動で設定を追加、再起動してくれます。

/etc/nginx/certsに証明書のあるディレクトリをbind mountしておけば、SSL接続もできますが、CloudFrontを使う予定なのでコメントアウトしています。

MySQL

XSERVERのバージョンに合わせて5.7を使用していますが、新しいバージョンでも問題ないと思います。

データベースのデータはbind mountして、永続化しています。

MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORDをしてすることで、root以外のユーザーも作成されます。このユーザーはMYSQL_DATABASEに対してのみフルアクセスがあるので、あとでphpMyAdminからrootでログインして、2つ目のWordPress用にdatabase 作成及び、権限付与が必要です。

CREATE DATABASE wordpress_2;
GRANT ALL PRIVILEGES ON wordpress_2.* TO wordpres@'%';

WordPressのセットアップ

どちらのWordPressもほぼ設定は同じです。WORDPRESS_DB_NAMEとVIRTUAL_HOSTが違うだけです。

version: '3'

services:
   wordpress:
     volumes:
       - ./wordpress/wp-content:/var/www/html/wp-content  
     image: wordpress:latest
     restart: always
     environment:
       WORDPRESS_DB_NAME: wordpress_1
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress_pass
       VIRTUAL_HOST: example1.com
     networks:
       - front

networks:
  front:
    external:
      name: shared_default

Networks

共有サービスと通信するため、networkに共有サービス(sharedディレクトリに作成)のdefaultネットワークを指定しています。docker-compose.ymlが別でも共通のネットワークを使うことでmysqlへはdbという名前で接続できます。

VIRTUAL_HOST

nginx-proxyでルーティングするためのhost名です。DNSの設定を変更するまではドメインではアクセスできないので、当面はAWSのパブリックDNSかIPを使ってテストします。

Volumes

インストールしたプラグインやテーマを保存するため、wp-contentをbind mountします。
ただし、そのままではパーミッションがうまく設定されず以下の問題が出ます。

  1. WordPressにはbind mountしたwp-contentには書き込み権限がない。
    bind mountしたディレクトリはオーナーが元々ディレクトリを作成したユーザー(ec2-user)もしくはroot(コンテナ実行時にディレクトリが存在していなかった場合)です。コンテナ内のapacheの実行ユーザーはwww-dataで、両者とも異なるためディレクトリに書き込みができません。
  2. wp-content以下のファイルはec2-userから変更できない。
    ファイルのオーナーはwww-data:www-dataなので、ec2-userからは直接変更できない。(sudoすれば可能。)

どちらかというと1の問題の方が困りますが、2もテーマの編集等をホストマシンから直接やろうとすると不便です。

解決方法1 ホストマシーンにグループ作成

ホストマシンにwww-dataグループ(GID:33)を作成し、ec2-userを追加。wp-content以下はオーナーをec2-user:www-dataに変更し、groupに書き込み権限を与える。

sudo groupadd -g 33 www-data
sudo usermod -aG www-data eu2-user
chown -R ec2-user:www-data wp-content
chmod -R 775 wp-content 

解決方法2 コンテナにユーザー作成

コンテナ内にec2-userと同じ、UID=1000のユーザーを作成し、apacheの実行ユーザーに指定すします。buildディレクトリを作成し、以下のDockerfileをおきます。

FROM wordpress:latest
RUN groupadd -g 1000 docker
RUN useradd -m -u 1000 -g 1000 docker
RUN chown -R docker:docker /var/www/html

docker-compose.yamlをDockerfileからbuildするよう変更し、apacheの実行ユーザー指定のための環境変数を変数を追加します。

version: '3'

services:
   wordpress:
     volumes:
       - ./wordpress/wp-content:/var/www/html/wp-content  
     build: ./build
     restart: always
     environment:
       APACHE_RUN_USER: docker
       APACHE_RUN_GROUP: docker
       WORDPRESS_DB_NAME: wordpress_1
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress_pass
       VIRTUAL_HOST: example1.com
     networks:
       - front

networks:
  front:
    external:
      name: shared_default

上記のいずれかでアクセス権の問題は解消します。コンテナ内にユーザーを作成する方が、少し手間ですが、ポータブルで綺麗な解決方法でしょうか。

以上でWordPressのセットアップができました。次回はブログコンテンツの移行、ドメイン割当を行います。

モバイルバージョンを終了