Dockerを使ってサクッとHTTPS対応WordPress環境を構築する

WordPress環境を構築する際、みなさんはどうやっていますか?

Dockerを使うとサクッとWordPress環境を構築出来ます。

さらに、WordPressやデータベースの構築だけではなく、
Let’s Encrypt に対応したDockerイメージを利用することで、HTTPS対応も簡単にできてしまいます。

今回は、HTTPS対応のWordPress環境をささっと構築する方法を紹介します。

目次

前提条件

  • Dockerを利用できること
  • インターネットからHTTPリクエストを受け付けられること

Dockerを利用できること

環境構築には、Docker及びDocker Composeを利用します。
docker 及びdocker-compose コマンドを実行できることが前提です。

インターネットからのHTTPリクエストを受け付けられること

HTTPS対応のWordPressを構築するので、
当然インターネットから今回構築する環境に対してHTTPS(443番ポート)でアクセスできる必要があります。

また、今回紹介するSSL対応では、SSLサーバ証明書としてLet’s Encryptを利用する方法を紹介します。
Let’s EncryptのSSLサーバ証明書の期限は90日間となっていて、割と頻繁に更新してあげる必要があります。
Let’s EncryptのSSLサーバ証明書の更新方法としていくつか種類がありますが、
今回紹介するSSLサーバ証明書の更新では、Let’s Encryptサーバ側からのHTTPリクエストを受け付けることで更新します。したがって、インターネットから今回構築する環境に対してHTTP(80番ポート)でアクセスできる必要があります。

構築環境

OS

僕は、Ubuntu 20.04 LTS上に構築しました。
CentOS でも AmazonLinux でも同様に構築できると思いますが、試してはいません。

WordPress推奨環境

まずは、WordPressの推奨環境を確認します。

要件|WordPress.org によると、推奨環境は以下のようになっています(2021年2月時点)

  • PHP バージョン 7.4 以上。
  • MySQL バージョン 5.6 以上、または MariaDB バージョン 10.1 以上。
  • HTTPS 対応

今回は、この推奨環境に従って、WordPress環境を構築していきます。

構成

WordPress環境を構築するにあたって、4種類のコンテナを用意します。
コンテナイメージは全てDockerHubから取得します。自前でイメージをビルドする必要はありません。

コンテナイメージ
https-portalsteveltn/https-portal:1
nginxnginx:stable
wordpresswordpress:php7.4-apache
mysqlmysql:5.7

構成図

https-portal,nginx,Wordpress,mysqlの4種類のコンテナを使ってWordPressを構築します。まず、https-portalコンテナでインターネットからのHTTPS通信を受け付けてnginxコンテナにHTTP通信で転送します。nginxコンテナは設定したルールに従ってWordPressのURLであれば、WordPressコンテナに転送します。

簡単に説明すると、

  • インターネットからのHTTPS通信を https-portal コンテナで受け付けます。
  • https-portal コンテナは、nginx コンテナにHTTPで転送します。
  • nginx コンテナはWordPress用のURLであることを確認して、wordpress コンテナに転送します。

それぞれのコンテナの役割について、もう少し詳しく説明します。

利用するコンテナイメージ

https-portal

https-portal は、簡単にHTTPS対応のWebサーバを構築できるDockerイメージで、
このDockerイメージを利用すると、無料のSSLサーバ証明書を提供するLet’s Encryptを利用してHTTPS対応することができます。

証明書の発行はもちろんのこと、面倒な証明書の定期更新まで、https-portalが全て自動でやってくれます。

注意点1)証明書の取得/更新のためにHTTP通信を利用する

Let’s Encryptから証明書を取得するときは、ACME 標準で定義されている「チャレンジ」を使用して、証明書が証明しようとしているドメインを所有していることを確認します。

いくつか「チャレンジ」の種類がありますが、https-portalで対応しているのは HTTP-01チャレンジ という方法です。HTTP-01チャレンジ では、80番ポートで Let’s Encrypt からのHTTPリクエストを受け付けて、取り決め通りのレスポンスが返却されることで検証が成功します。

したがって、HTTPS(443番ポート)だけではなく、HTTP(80番)でもインターネットからのHTTPリクエストを受け付けられるようにしておく必要があります。

注意点2)ワイルドカード証明書に対応していない

https-portal では、Let’s Encrypt からSSLサーバー証明書を取得したいドメイン名を指定しますが、
その時にワイルドカード証明書(例 *.example.com)の形式で指定することができません。

GitHubのissueも立っていてcontributor の方からの返信もあるので、
いずれ出来るようになるかもしれません。

nginx

Nginxの動作環境を構築することができるコンテナイメージです。
リバースプロキシとしてNginxを利用します。

  • ドメインベースのHTTPリクエストの振り分け
  • gzip による静的コンテンツの圧縮
  • proxy_cache によるキャッシュによる応答の高速化

を担当します。

wordpress

PHPの動作環境とWordPressの動作環境を構築することができるコンテナイメージです。
ここがメインのところ。(最低限このコンテナとデータベースさえあれば、動作します。)

mysql

MySQLを構築することができるコンテナイメージです。

設定

設定ファイルの構成

$ tree
.
|-- .env
|-- docker-compose.yml
|-- nginx
|   |-- conf.d
|   |   |-- wordpress.conf
|   |   `-- www.conf
|   `-- nginx.conf
`-- wordpress-php
    `-- conf.d
        `-- uploads.ini

Docker Compose

docker-compose.ymlを作成します。ユーザ名やパスワードは、 .env ファイルに書きます。

version: '3'
services:

  # SSL対応
  https-portal:
    image: steveltn/https-portal:1
    container_name: web_https-portal
    ports:
      - 80:80
      - 443:443
    depends_on:
      - nginx
    restart: always
    volumes:
      - ./certs:/var/lib/https-portal
    environment:
# 本番運用するときはコメントアウトを外してください
#      STAGE: 'production'
      DOMAINS: >-
        example.com -> http://nginx
      WORKER_PROCESSES: auto
      WORKER_CONNECTIONS: 2048
      CLIENT_MAX_BODY_SIZE: '128M'

  # Nginx
  nginx:
    image: nginx:stable
    container_name: web_nginx
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/log:/var/log/nginx
      - ./nginx/www:/var/www
    depends_on:
      - wordpress
    restart: always

  # WordPress+PHP7.4
  wordpress:
    image: wordpress:php7.4-apache
    container_name: web_wordpress
    environment:
      - WORDPRESS_DB_HOST=${WORDPRESS_DB_HOST}
      - WORDPRESS_DB_USER=${WORDPRESS_DB_USER}
      - WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
      - WORDPRESS_DB_NAME=${WORDPRESS_DB_NAME}
    volumes:
      - ./wordpress:/var/www/html
      - ./wordpress-php/conf.d/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    depends_on:
      - mysql
    restart: always

  # MySQL
  mysql:
    image: mysql:5.7
    container_name: web_mysql
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
    restart: always
# mysql
MYSQL_ROOT_PASSWORD={MySQLの管理者パスワード}
MYSQL_USER={作成するMySQLユーザー}
MYSQL_PASSWORD={作成するMySQLユーザーのパスワード}
MYSQL_DATABASE=wordpress

# wordpress
WORDPRESS_DB_HOST=mysql
WORDPRESS_DB_USER={MySQLユーザー}
WORDPRESS_DB_PASSWORD={MySQLユーザーのパスワード}
WORDPRESS_DB_NAME=wordpress

https-portal の設定

設定は、docker-compose.yml のみですが、注意点があります。

STAGE: ‘production’ は動作確認段階では有効にしない

SSLサーバー証明書の取得に失敗しすぎると、
Let’s Encrypt のレート制限に引っかかってしまう可能性があるためです。

ステージング環境だと1時間に60回まで出来ますが、本番環境は1時間に5回までしか失敗できません。

There is a Failed Validation limit of 5 failures per account, per hostname, per hour. This limit is higher on our staging environment, so you can use that environment to debug connectivity problems. Exceeding the Failed Validations limit is reported with the error message too many failed authorizations recently.

https://letsencrypt.org/docs/rate-limits/

ちなみに、何も指定しない場合は、STAGE: 'staging'が設定され、
Let’s Encrypt のステージング環境が利用されます。

However if you play around with the image a lot, you can hit the limit. That’s why STAGE is staging by default, and thus we use the Let’s Encrypt staging server. When you have finished your experiments and feel everything is good, you can switch to production mode with STAGE: 'production'.

https://github.com/SteveLTN/https-portal#about-rate-limits-of-lets-encrypt

CLIENT_MAX_BODY_SIZE の設定

画像や動画をアップロードできるように設定します。
個人用途のつもりで設定しているので128MBで設定していますが、
誰でも画像アップロードできるようなサービスの場合は、もっと厳しめに設定したほうが良いでしょう。

nginx の設定

まずは、最低限必要な設定を記載します。
gzipの設定やcache_proxyの設定とか色々あるんですが、それらについて書いていると長くなるので別記事にします。

用意する設定ファイル

$ tree nginx/
nginx
|-- conf.d
|   |-- wordpress.conf
|   `-- www.conf
`-- nginx.conf

nginx.conf

user nginx;
worker_processes        auto;
worker_rlimit_nofile    80000;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
  worker_connections  2048;
  multi_accept  on;
  use epoll;
}

http {
  include /etc/nginx/mime.types;
  default_type  application/octet-stream;

  include /etc/nginx/conf.d/*.conf;
}

wordpress.conf

server {
        listen 80;
        server_name example.com;

        location / {
                proxy_pass http://wordpress/;
                proxy_redirect          off;

                # リクエストヘッダーの情報を下位のサービスに伝える
                proxy_set_header        Host            $host;
                proxy_set_header        X-Real-IP       $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

                # タイムアウト設定
                proxy_connect_timeout   10;
                proxy_send_timeout      10;
                proxy_read_timeout      60;

                # 画像や動画をアップロードへの対応
                client_body_buffer_size 128M;
                client_max_body_size    128M;
                proxy_buffer_size       32K;
                proxy_buffers           50 32K;
                proxy_busy_buffers_size 64K;
        }
}

wordpress の設定

用意する設定ファイル

$ tree wordpress-php/
wordpress-php/
`-- conf.d
    `-- uploads.ini

uploads.ini

file_uploads = On;
memory_limit = 256M;
post_max_size = 192M;
upload_max_filesize = 128M;

128MBまでの画像や動画をアップロードに対応するために設定

mysql の設定

(docker-compose.yml のみで追加の設定は必要ありません。)

docker-compose でサクッと構築

コンテナ起動

docker-compose up -d でコンテナイメージのダウンロード、コンテナの起動が行われます。

$ sudo docker-compose up -d

起動確認

docker psでコンテナ一覧を表示して、起動に成功していることを確認します。

$ sudo docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                PORTS                                      NAMES
db79dec54bb3        wordpress:php7.4-apache    "docker-entrypoint.s…"   13 days ago         Up 4 days             80/tcp                                     web_wordpress
1cbf36e86bd4        steveltn/https-portal:1    "/init"                  7 weeks ago         Up 4 days             0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   web_https-portal
e53e618b1ffe        nginx:stable               "/docker-entrypoint.…"   7 weeks ago         Up 3 days             80/tcp                                     web_nginx
1a7ca435f9ae        mysql:5.7                  "docker-entrypoint.s…"   7 weeks ago         Up 4 days             3306/tcp, 33060/tcp                        web_mysql

無事、起動に成功していれば良いですが、
起動に失敗していると、STATUS欄が Up 4 days とかではなく Exited (127) みたいに表示されます。

終了コードしか表示されないので原因を特定できない場合が多いです。
エラー原因を調査するには、コンテナのログを確認することになります。

コンテナのログを確認

docker logsでコンテナのログを確認します。

$ sudo docker logs [コンテナ名]

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
目次