ゼロからEC2+DockerでWordpressをnginx-proxyを利用してサブドメインに構築(SSL対応)

# はじめに
この記事では，ゼロからEC2とDockerを使って，Wordpressを nginx-proxyを利用してサブドメインに構築していきます．もちろんドメインでもできます．また，`nginx-proxy-lets-encrypt`を用いてSSL化も行っています．
注意としては，AWSコンソールのUIは頻繁に変更されているので，もしかしたら異なっている可能性があります．

# この記事の目的
他にもたくさんのEC2でWordpressを構築している記事を見てきましたが
- SSL化をしていない
- Dockerを使っていない
- サブドメインでなくドメインを使用している
といったものが多く，非常に苦労しました．
なのでこの記事はできるだけ丁寧に細かく記載しましたので，誰かの役に立てることを願っています．

# 技術
- EC2(Ubuntu18.04)
- Docker(ngix-proxy, wordpress, nginx-proxy-lets-encrypt, mysql)
- Route53

# EC2の設定
### EC2インスタンスの起動
AWSコンソールにアクセスして，`EC2`と検索してページ移動します．


![スクリーンショット 2019-11-08 18.50.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/677fcf90-c260-be3b-3358-3b731fef44fb.png)

左側のメニューでインスタンスをクリックします．

![スクリーンショット 2019-11-08 19.02.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/31d60bfa-b044-29a7-74af-93d886b8b692.png)

上の方にあるインスタンスの作成ボタンをクリックします．

![スクリーンショット 2019-11-08 19.03.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/07801522-9afc-3218-df2d-51c3addb0ff8.png)


色々作れますが，今回はUbuntu18.04を作っていきます．64ビット(x86)にチェックを入れて，青の選択ボタンを押します．

![スクリーンショット 2019-11-08 19.03.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/f9fb2dfe-0c12-303d-e976-974137852f8d.png)

t2.microに選択を入れて，右下にある`確認と作成`という青いボタンを押します．(細かい設定がしたい場合は，`次のステップ:インスタンスの詳細と設定`ボタンを押すと設定できます．Wordpressを使う場合は，インスタンスサイズはt2.micro以上にしておきましょう．)

ページ遷移して，右下にある`起動`ボタンを押します．

次にダイヤログでキーペアを作成するか聞かれます．`新しいキーペアの作成`を選択し，適当なキーペア名をつけ，`キーペアのダウンロード`ボタンを押します．このキーペアがSSHでログインする際に必要になります．ダウンロードが終わったら，`インスタンスの作成`ボタンを押して，数分待つとインスタンスが起動します．


![スクリーンショット 2019-11-08 19.12.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/a1ce652d-8f26-1c14-14a0-ad76acebe81d.png)


### EC2のサーバーにログイン
ブラウザのEC2インスタンスのページで作成した`インスタンスの状態`という項目が`running`になったら．ログインしていきます．
Macのターミナルを開いて,ダウンロードしたmykey.pemのあるディレクトリまで移動します．(`$ ls`と打ってmykey.pemが出てきたらok)
次のようにコマンドを打ちます．
`XXXXX`の部分にはパブリック DNS (IPv4)が入ります．ブラウザでインスタンスにチェックを入れると下の方にメニューが表示されます．その中にパブリック DNS (IPv4)があります．(etc. `ec2-9-999-99-99.ap-northeast-0.compute.amazonaws.com`)

```
$ chmod 400 mykey.pem

$ ssh ubuntu@XXXXX -i mykey.pem -p 22
```

もしsshコマンドで失敗した時は`$ sudo ssh ubuntu@XXXXX -i mykey.pem -p 22`と`sudo`をつけたらうまくいくかもしれません．

これでターミナルのユーザー部分が`ubuntu@〇〇〇〇`みたいになっていたら，ログイン成功です．(〇〇〇〇にはサーバーのIPアドレスが入ります．)

### EC2にパスワード，キーペアなしでログイン(任意)
EC2にログインするたびに，パスワードやキーペアを使うのは非常に手間です．
[お前らのSSH Keysの作り方は間違っている](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)を参考に設定しておきましょう．

### セキュリティを高める(任意)
この記事ではubuntuユーザーで話を進めていますが，通常rootやデフォルトユーザー(ubuntu)ではログインできないようにしたり，sshのポート番号を変更してセキュリティを高めます．
[そこそこセキュアなlinuxサーバーを作る](https://qiita.com/cocuh/items/e7c305ccffb6841d109c)を参考に対策をしておきましょう．

# Dockerのインストール
参考文献 : [Ubuntuにdockerをインストールする]
(https://qiita.com/tkyonezu/items/0f6da57eb2d823d2611d)

[公式](https://docs.docker.com/install/linux/docker-ce/ubuntu/)の通り順番にコマンドを実行していきます．

まだDockerが何かよくわかっていない方は[創好リナのDocker入門講座](https://www.youtube.com/watch?v=5d8O7jm7Q5c)(Youtube，2018/07/29公開)がわかりやすいです．

```
$ sudo apt-get update

$ sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

$ sudo apt-key fingerprint 0EBFCD88

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

$ sudo apt-get update

$ sudo apt-get install -y docker-ce

$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/version: dial unix /var/run/docker.sock: connect: permission denied
```

最後のコマンドで`permission denied`というエラーが起きています．

### dockerグループにユーザーを追加する
参考文献 : [dockerコマンド実行時にエラー"Got permission denied while trying to connect to the Docker daemon socket"が出るとき
](https://akamist.com/blog/archives/3536)

これはdockerグループにユーザーを追加することで直ります．

```
$ sudo gpasswd -a [ユーザー名] docker
Adding user ubuntu to group docker

$ exit
```
dockerグループに追加した後，一回`exit`コマンドを使ってユーザーからログアウトしましょう．再びユーザーにログインして`docker version`コマンドを入力し`Got permission denied~`のエラーが消えていることを確認しましょう．

```
$ docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
```

これでDockerのインストールは完了です．

### Docker Composeのインストール
参考文献 : [【WordPress】DockerでWordPress開発環境を爆速で構築する【Docker Compose】](https://tkzo.jp/blog/wordpress-with-docker-compose/)

Dockerはコンテナ型の仮想環境です．ではDocker Composeは何かというと，
- bulid, run, startなどを楽にしてくれる
- 複数のコンテナを1つのyamlファイルで定義できる
というメリットがあります．

次のコマンドでDocker Composeがインストールできます．

```
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
 % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   617    0   617    0     0   2063      0 --:--:-- --:--:-- --:--:--  2063
100 15.4M  100 15.4M    0     0  4361k      0  0:00:03  0:00:03 --:--:-- 5899k
```

なお，コマンドの`1.24.0`の部分は[Docker ComposeのGithub](https://github.com/docker/compose/releases)を確認して，適宜変更してください．

インストールできているか確認します．

```
$ docker-compose --version
-bash: /usr/local/bin/docker-compose: Permission denied
```

権限がないよっと言われしまったので，`chmodコマンド`を打ち，再度確認します．

```
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.24.0, build 0aa59064
```

これでDocker Composeが使えるようになりました．


### EC2のセキュリティグループの設定
EC2のセキュリティグループでHTTPとHTTPSを許可しておかないと，Wordpressを動かしてもブラウザでアクセスすることができません．
AWSコンソールでEC2のページに移動し，作成したインスタンスをクリックします．
そして，下の方に表示されるインスタンスの`説明`項目の中に`セキュリティグループ`というのがあるのでクリックします．

![スクリーンショット 2019-11-27 17.29.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/1b9c8f12-9189-89b6-a2aa-7dca1b6bb04c.png)

ページ移動して下のメニューの`インバウンド`をクリックし，`編集`というボタンがあるのでクリックします．

![スクリーンショット 2019-11-27 17.31.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/1cfd1a27-dcdd-7378-c75c-2b4e23cb61ff.png)

デフォルトではSSHしかないのでHTTPとHTTPSを追加します．また，SSHのポートは0.0.0.0/0になっており(どこからでもログイン出来る)，攻撃を受ける可能性が高いのでソースを`任意の場所`か`マイIP`に変更しておきましょう．(下の画像は0.0.0.0/0のままですが)
例えば自分の家で`マイIP`を選択すると，自分の家のwifiからしかSSH出来ないようになります．
最後に保存を押して，EC2インスタンスを再起動しておきましょう．

![スクリーンショット 2019-11-27 17.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/387958f1-9f67-816e-243e-68e668bdda5c.png)

# Route53の設定
Route53ではドメインとサブドメインの設定をしていきます．ドメインやサブドメインがよくわかっていない方は[独自ドメイン？サブドメイン？ドメインについて理解しよう！](https://www.asobou.co.jp/blog/web/domain)に目を通しておきましょう．

Route53でドメイン取得とDNSの登録は[AWSだけで独自ドメインを取得して自分のWebページを公開するまで[画像で解説] 2018冬](https://qiita.com/ymzk-jp/items/ae115ed6d0fd2d383cec)を参考に導入しましょう．
[4 Aレコードが増えたことを確認](https://qiita.com/ymzk-jp/items/ae115ed6d0fd2d383cec#4-a%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C%E5%A2%97%E3%81%88%E3%81%9F%E3%81%93%E3%81%A8%E3%82%92%E7%A2%BA%E8%AA%8D)までやればOKです．
なお，ドメインの取得後やDNSの登録後は反映に数時間かかる場合があります．僕は`.io`のドメインを使いますが，好きなものをつかってOKです．

次にサブドメインを設定します．
まずRoute53のページにいくと，左のメニューが`ダッシュボード`になっているので，`ホストゾーン`を選択します．
<img width="235" alt="スクリーンショット 2019-11-27 15.18.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/0f094ae1-e85d-b41c-d5c1-d457f9b02b9e.png">

次に登録しているドメイン名をクリックします．

![route53_hostzone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/42741169-b92b-35f1-db32-9676a387f510.png)

`レコードセットの作成`ボタンを押します．
<img width="421" alt="スクリーンショット 2019-11-27 15.23.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/03b7c60a-7120-7a62-8652-e259f7cc0d9d.png">

`レコードセットの作成`というメニューが表示されるので，名前にはサブドメインに設定したい名前，値にはEC2の`IPv4 パブリック IP`を入力し，タイプは`A`のままにしておいて作成ボタンを押します．


![new_recordset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/cda497b7-d689-cf4e-6667-2ab9a7aaf4d2.png)


EC2にドメインが割り当てられているか確認するには，ターミナルで

```
$ host [test.XXX.io.]
[test.XXX.io.] has address 54.123.456.987
```

と表示されると思います．`[test.XXX.io.]`には先ほどのドメインまたはサブドメインを入力し，`54.123.456.987`の部分がEC2の`IPv4 パブリック IP`と一致していたらOKです．

# Dockerでngix-proxy, wordpress, nginx-proxy-lets-encrypt, mysqlを導入
`ngix-proxy`はnginxで楽にvirtualhostなどを設定できるやつです．`nginx-proxy-lets-encrypt`はngix-proxyで構築したWordpressなどにlet's EncryptのSSL証明書を簡単に取得してくれます．

### emacsのインストール(任意)
vim派の人はしなくて良いです．
ファイルをいじるのでemacsを入れておきます．
まずEC2にログインします．

```
$ sudo apt-get install emacs

$ emacs --version
GNU Emacs 25.2.2
Copyright (C) 2017 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GNU Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.
```

### Docker Composeにコードを書いていく
ngix-proxy, wordpress, nginx-proxy-lets-encrypt，mysqlを導入していきます．
EC2にログインして以下のようにディレクトリ，ファイルを作成します．(名前は特に気にしなくて良い)
`proxyディレクトリ`にはngix-proxy, nginx-proxy-lets-encryptを書いて，`testディレクトリ`にはwordpress，mysqlについて書いてあります．

```
wordpress/
├── proxy
│   └── docker-compose.yml
└── test
    └── docker-compose.yml
```

```:wordpress/proxy/docker-compose.yml
version: '3'
# proxy
services:

  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - html:/usr/share/nginx/html
      - dhparam:/etc/nginx/dhparam
      - vhost:/etc/nginx/vhost.d
      - certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /srv/docker/nginx-proxy-with-encrypt/log:/var/log/nginx
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    restart: always

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-proxy-lets-encrypt
    depends_on:
    - "nginx-proxy"
    volumes:
    - certs:/etc/nginx/certs:rw
    - vhost:/etc/nginx/vhost.d
    - html:/usr/share/nginx/html
    - /var/run/docker.sock:/var/run/docker.sock:ro

volumes:
  certs:
  html:
  vhost:
  dhparam:

networks:
  default:
    external:
      name: common_link
```

```:wordpress/test/docker-compose.yml
version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     container_name: test
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       VIRTUAL_HOST: [test.XXX.io.]
       LETSENCRYPT_HOST: [test.XXX.io.]
       LETSENCRYPT_EMAIL: [自分のメールアドレス]

volumes:
    db_data: {}

networks:
  default:
    external:
      name: common_link
```

`[test.XXX.io.]`にはRoute53で登録したドメインまたはサブドメイン，`[自分のメールアドレス]`には自分のメールアドレスを入力します．`container_name`は`test`になっていますが好きな名前をつけてOKです．

さらに他のサブドメインでWordpressを作りたい時は，`:wordpress/test/docker-compose.yml`を複製していく感じです．その際は`testディレクトリ`ではなく，名前を変えて新しいディレクトリを作成してください．また，ドメインまたはサブドメイン名も変更しておきましょう．

### 共有ネットワークの作成

次に共有ネットワークを作成します．

```
$ docker network create --driver bridge common_link
```

### Docker立ち上げ

最後に`proxyディレクトリ`と`testディレクトリ`のdockerを立ち上げます．

```
$ pwd
/home/ubuntu/wordpress

$ cd proxy/

$ docker-compose up -d

$ cd ../test/

$ docker-compose up -d
```

そして自分のドメインまたはサブドメイン(`[test.XXX.io.]`)をブラウザで検索して，Wordpressの初期画面が表示されたら成功です．ちゃんとSSL化もしています．

![wordpress_default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294876/1b87c98d-16d1-7fa1-1e56-df085293360f.png)

# 困ったときの対処

### ブラウザでアクセスしても`タイムアウト`または`このサイトにアクセスできません`となる
これはEC2のセキュリティグループでHTTPとHTTPSを許可していない可能性があります．また，セキュリティグループを再設定した後はインスタンスを再起動する必要があります．

### ブラウザでアクセスすると`Internal Server Error`と表示される
これはDockerの設定が間違えている可能性があります．`docker-compose.yml`や`共有ネットワーク`をもう一度チェックしましょう．
Wordpressを作るのではなく，nginxが立ち上がるか確かめてみると良いかもしれません．
適当に`tmpディレクトリ`を作ってnginxが動くか確認しましょう．

```:wordpress/tmp/docker-compose.yml
version: '3'
# service
services:

  web:
    image: nginx
    container_name: nginx_test
    environment:
      VIRTUAL_HOST: 
      LETSENCRYPT_HOST: [test.XXX.io.]
      LETSENCRYPT_EMAIL: [自分のメールアドレス]
    restart: always

networks:
  default:
    external:
      name: common_link
```