docker-composeでさくっとhttpsなWordPressを公開する

# 背景
この度、知り合いにホームページ作成を依頼されました。制作期間が仕事の片手間で1週間しかなく、ほぼ個人サイトということもあり、(ついでに言うとただ働きなので)ここはdocker-composeでさくっと仕上げようと考えました。一応公開するので、Let's Encryptでhttps化も実施しました。また、ついでだから自分用のサイトも公開してしまおうと思い、複数サイト公開可能な構成にしました。
今更なトピックではありますが、自分用の備忘録として手順を残したいと思います。

# 準備
### 環境
今回は下記の環境で構築しました。

| 種別             | 利用環境 　　　　　 | バージョン       |
|:-----------------|------------------:|:---------------:|
| サーバ           | さくらVPS          | v4              |
| ドメイン取得      | お名前.com         | -               |
| SSL証明書        | Let's Encrypt      | -               |
| サーバOS         | ubuntu             | 16.04           |
| クライアントOS    | macOS Catalina    | 10.15           |
| docker           | -                 | 18.09.7         |
| docker-compose   | -                 | 1.22.0          |

### 前提条件

- OSのインストールされたサーバが起動済みであること
- 取得したドメインがDNSレコードに登録されていること

# 構築手順
大まかには、下記の手順で構築していきます。
1. ファイアウォールの設定
2. FTPの導入
3. dockerおよびdocker-composeのインストール
4. 共有コンテナのディレクトリとファイルの作成
5. サイト毎のディレクトリとファイルの作成
6. dockerネットワークの作成 
7. アップロードサイズ制限の変更ファイル作成
8. コンテナの起動
9. ２つ目以降のサイト立ち上げ

なお、以降の解説では、サーバのアカウントをubuntu、サイト1のドメインをexample.comとして記述していきます。

ディレクトリ構成は下記のように、
shareというディレクトリにプロキシなどの共通で利用するコンテナのファイルを、
同一ディレクトリにそれぞれのサイト名で、サイト毎のコンテナのファイルをまとめます。
　~/public_html
　┣share # リバプロ等、各サイトで共通のコンテナ用ディレクトリ
　┣ サイト1 # １つ目のサイト
　┣ サイト2 # ２つ目のサイト
　┣ ...

また、WordPressの管理画面からアップロードファイルサイズ制限の変更をしておきます。
デフォルトの2MBでは、ほとんどのテーマがアップロードできないと思うので。

## 1. ファイアウォールの設定
ターミナルからSSH接続して、ファイアウォールを設定します。
例では80番やFTP関連も開けていますが、必要に応じて取捨選択してください。

```
# SSHホストキーを一度作成している場合は、接続する前に削除する
$ ssh-keygen -R example.com

# ssh接続
$ ssh ユーザ名@example.com

# ファイアウォールの設定と必要なポートの通信許可
$ sudo ufw enable
$ sudo ufw allow 80
$ sudo ufw allow 443
$ sudo ufw allow 22
$ sudo ufw allow 21
$ sudo ufw allow 20
$ sudo ufw reload

# ステータスの確認
$ sudo ufw status
To                         Action      From
--                         ------      ----
80                         ALLOW       Anywhere                  
443                        ALLOW       Anywhere                  
22                         ALLOW       Anywhere                  
20                         ALLOW       Anywhere                  
21                         ALLOW       Anywhere                  
80 (v6)                    ALLOW       Anywhere (v6)             
443 (v6)                   ALLOW       Anywhere (v6)             
22 (v6)                    ALLOW       Anywhere (v6)             
20 (v6)                    ALLOW       Anywhere (v6)             
21 (v6)                    ALLOW       Anywhere (v6) 
```

## 2. FTPの導入
続いてFTPを導入します。手動でバックアップを取るとか、
プラグインをインストールする予定がないのであれば飛ばしてしまって良いと思います。

```
# パッケージの更新
$ sudo apt update
$ sudo apt upgrade

# vsftpdの導入
$ sudo apt install vsftpd -y

# 設定ファイルを編集する
$ sudo vi /etc/vsftpd.conf

#ファイル内から以降の設定記述箇所を探してコメントアウト、編集する
# 匿名ユーザのアクセス拒否
anonymous_enable=NO
# ファイルシステム変更コマンド許可
write_enable=YES
# アスキーモードのアップロード許可
ascii_upload_enable=YES
# アスキーモードのダウンロード許可
ascii_download_enable=YES
# 設定したディレクトリより上層への移動を禁止する
chroot_local_user=YES
# リストファイルに記述されたユーザはchrootの対象から除外する
chroot_list_enable=YES
# リストファイルの場所を指定
chroot_list_file=/etc/vsftpd.chroot_list
# ディレクトリの一括アップロード・ダウンロードを許可
ls_recurse_enable=YES
# seccomp filterオフを追記
seccomp_sandbox=NO

# リストファイルの作成
$ sudo vi /etc/vsftpd.chroot_list

# 必要なユーザを記述する
ubuntu

# サービスのリスタート
$ sudo service vsftpd restart
```

## 3. dockerおよびdocker-composeのインストール
docker-composeはリポジトリからインストールします。

```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt install docker.io
$ sudo apt-get install curl
$ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# docker-composeコマンドを利用できるようにする
$ sudo chmod +x /usr/local/bin/docker-compose
```

## 4. 共有コンテナのディレクトリとファイルの作成
まずディレクトリを作成し、その中にdocker-compose.ymlを作成します。
MySQL、NginxのリバースプロキシとLet's encryptの証明書を取得、更新してくれるコンテナを立ち上げるようにします。

```
$ sudo mkdir share
$ cd share
$ sudo vi docker-compose.yml
```
docker-compose.ymlの内容は下記の通りです。

```public_html/share/docker-compose.yml
version: "2"

services:
  mysql:
    image: mysql:5.7
    container_name: mysql
    ports:
      - "3306:3306"
    volumes:
      - ./db/mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
    restart: always

  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    privileged: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./docker-compose.d/certs:/etc/nginx/certs:ro
      - ./docker-compose.d/htpasswd:/etc/nginx/htpasswd
      - ./conf.d:/etc/nginx/conf.d
      - /etc/nginx/vhost.d
      - /usr/share/nginx/html
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always

  letsencrypt-nginx:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: letsencrypt-nginx
    privileged: true
    volumes:
      - ./docker-compose.d/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    volumes_from:
      - nginx-proxy
    restart: always

networks:
  default:
    external:
      name: shared

```

## 5. サイト毎のディレクトリとファイルの作成
続いてサイト毎のディレクトリとdocker-composeを作成します。

```
$ cd ..
$ sudo mkdir example
$ cd example
$ sudo vi docker-compose.yml 
```
docker-compose.ymlは以下の通りに作成します。

```public_html/example/docker-compose.yml
version: "3"

services:
  wordpress:
    image: wordpress:latest
    container_name: example
    ports:
      - 9000:80
    volumes:
      - /home/ubuntu/public_html/example/html:/var/www/html
      - ./conf.d/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    environment:
      VIRTUAL_HOST: example.com # サイトのドメイン
      VIRTUAL_PORT: 9000
      LETSENCRYPT_HOST: example.com # サイトのドメイン
      LETSENCRYPT_EMAIL: account@mail # 証明書を取得するためのアドレス
      LETSENCRYPT_TEST: "false"
      WORDPRESS_DB_PASSWORD: password # MySQLパスワード
      WORDPRESS_DB_NAME: example.com # 任意のDB名
    external_links:
      - mysql
    restart: always

networks:
  default:
    external:
      name: shared
```
## 6. dockerネットワークの作成
以下のコマンドを実行して、dockerネットワークを作成します。

```
$ docker network create --driver bridge shared
```
## 7. アップロードサイズ制限の変更ファイル作成

WordPressの管理画面からアップロードできるテーマやメディアファイルのサイズ制限を変更します。
共有コンテナディレクトリおよびサイト毎の「conf.d」ディレクトリを作成して、その中に設定ファイルを追加します。
今回は20MBにしておきます。

```
$ sudo mkdir share/conf.d
$ sudo vi share/conf.d/max-size.conf

$ sudo mkdir example/conf.d
$ sudo vi example/conf.d/uploads.ini

```

それぞれのファイルの内容は以下の通りです。

```share/conf.d/max-size.conf
client_max_body_size 20M;
```

```example/conf.d/uploads.ini
upload_max_filesize = 20M;
post_max_size = 20M;
```

## 8. コンテナの起動
```
$ cd ../share
$ sudo docker-compose up -d

$ cd ../example
$ sudo docker-compose up -d
```
上記コマンドを実行した後に、[https://example.com](https://example.com)にアクセスすると、WordPressインストール画面が開きます。
![スクリーンショット 2019-12-02 22.50.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179668/eb7719cc-b8bf-b6a0-01bd-1740f8ac012e.png)

## 9. ２つ目以降のサイト立ち上げ
今回の構成だと、１つのMySQLに複数サイトのDBを作成して運用することになります。
この場合、WordPressは１つ名のサイトのデータベースは作成してくれますが、
２つ目以降のデータベースは作成してくれないので、インストール前に自分でデータベースを作成する必要があります。
以下の手順でデータベースを作成してください。

```
# MySQLコンテナにログイン
$ sudo docker exec -it mysql /bin/bash

# データベースの作成
$ mysql -u root -p
mysql> CREATE DATABASE site2 
```
上記で作成したデータベースに合わせて、「5. サイト毎のディレクトリとファイルの作成」の手順と同じように
２つ目のサイトのディレクトリとdocker-compose.ymlを作成してコンテナを起動すると、
１つ目のサイトと同じように、WordPressインストールサイトが開けます。

# あとがき
以上、細かい説明は省いて書いてしまいました。
それぞれの手順で細かく設定したい場合は、専門の記事を探していただければと思います。

今回はWordPressを立ち上げましたが、違うイメージからコンテナを起動すれば他のサービスも立ち上げられると思います。