WordPress環境をDocker(Local)とAWS(Production)で構築


表題の通り、WordPress環境をDockerとAWSで構築したのでその手順についてまとめます。

まとめる内容は以下になります。

- WordPressのLocal環境をDockerで構築
    - Webpackでscssとjsをcompileしてthemesディレクトリにoutput
    - scssとjsはassetsディレクトリで作業する
    - 開発ファイルはGitで管理する
- WordPressのProduction環境をAWSで構築
    - Public Subnet、Private SubnetでそれぞれEC2 InstanceにWordPressとMySQLをinstall
    - EC2 InstanceにGitを配置して開発ファイルをPullするとLocal作業が反映される

## Local環境

- WordPress の Local 環境を Docker で構築
- Webpack で js と scss ファイルを compile して themes に output

### Docker image の version

```
image: mysql:8.0.22
image: wordpress:latest
```

``` yaml:docker-compose.yaml
version: '3'

services:
  db:
    image: mysql:8.0.22
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: admin
      MYSQL_PASSWORD: password
    networks:
      - wpsite
  phpmyadmin:
    depends_on:
      - db
    image: phpmyadmin/phpmyadmin
    restart: always
    ports:
      - '8080:80'
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: password
    networks:
      - wpsite
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    ports:
      - '8000:80'
    restart: always
    volumes: ['./../src:/var/www/html']
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: admin
      WORDPRESS_DB_PASSWORD: password
    networks:
      - wpsite
networks:
  wpsite:
volumes:
  db_data:

```

### 開発作業

- scss と js の作業は`assets`ディレクトリ内で行う(`assets/css/`、`assets/js/`)
- `assets`ディレクトリ内で Webpack 起動
- scss と js を変更すると自動で compile されて themes に output
- js は`runtime.js`と`vendors.js`と`index.js`で分割される
- jQueryをinstall

``` javascript:webpack.config.js
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const themeName = 'original';

module.exports = {
  mode: 'production',
  entry: {
    index: ['./js/index.js', './css/style.scss'],
  },
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, `../src/wp-content/themes/${themeName}`),
    publicPath: '/',
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
  module: {
    rules: [
      {
        test: /\.js?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
      {
        test: /\.scss$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          'css-loader',
          'sass-loader',
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/style.css',
    }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),
  ],
};
```

webpack 起動コマンド

```
$ cd assets
$ npm start
```

## Local 環境

1. `/docker`ディレクトリに移動して docker(`docker-compose up -d`) 起動
2. `http://localhost:8000/`が wordpress の local URL
3. `http://localhost:8080/`が phpmyadmin の local URL

## tree

- `assets/js`のファイルを`src/wp-content/themes/original/js`に webpack で compile

```
├── assets
│   ├── css
│   │   └── style.scss
│   ├── js
│   │   └── index.js
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   └── webpack.config.js
├── docker
│   └── docker-compose.yaml
└── src
    ├── index.php
    ├── wp-admin
    ├── wp-config-sample.php
    ├── wp-content
        ├── index.php
        ├── languages
        ├── plugins
        ├── themes
            ├── index.php
            ├── original
                └── css
                    └── style.css
                └── js
                    └── index.js
                    └── runtime.js
                    └── vendors.js
```

## gitignore

```
src/.htaccess
src/wp-config.php
src/wp-content/uploads/
src/wp-content/upgrade/
```

## Docker コマンド

コンテナ表示

```
$ docker ps
```

image 一覧

```
$ docker images
```

コンテナ起動

- `-d`を実行すると、コンテナはバックグラウンドで起動し、そのまま実行し続けます。

```
$ docker-compose up -d
```

コンテナ停止

```
$ docker-compose down
```

## 本番環境

- AWS で構築
- Public Subnet
  - Apatch を install して Web サーバーとする
  - Internet Gatewayで外部からの通信を許可
- Private Subnet
  - NAT Gatewayを介して外部からの通信を可能にするが、サブネットからは通信を不可
  - MySQL を install して DB サーバーとする
  
### 構成図

![WordPress環境(docker(local)、AWS(prod))](https://user-images.githubusercontent.com/20336590/104121790-61692000-5384-11eb-95dc-bfa7666bec54.png)


SSH でログイン

```
$ ssh -i {秘密鍵}.pem ec2-user@{IPv4パブリックIP}
```

### Web サーバーを踏み台として DB サーバーに SSH ログインして MySQL をinstall

- DB サーバーはインバウンドでInternetと接続してない
- インバウンドで SSH での接続を許可しているので Web サーバーを踏み台に SSH ログインする
- SSH ログインするには pem key を Web サーバーに配置する
- NAT GatewayでPublic Subnetを通してInternetに接続できるようにする
- DB サーバーにログインして MySQL をinstallする

pem key を scp コマンドで Web サーバーにコピーして配置

```
$ scp -i {秘密鍵}.pem {秘密鍵}.pem ec2-user@{IPv4パブリックIP}:~/
```

DB サーバーに SSH ログイン

```
$ ssh -i {秘密鍵}.pem ec2-user@{プライベート IPv4 アドレス}
```

参考サイト

- [Amazon Linux2 の MariaDB を MySQL に差し替えでつまずいた点](https://qiita.com/miriwo/items/eb09c065ee9bb7e8fe06)
- [AWS EC2 AmazonLinux2 MySQL root ユーザの初期パスワードの確認方法](https://qiita.com/miriwo/items/457d6dbf02864f3bf296)

### MySQL コマンド

MySQL 起動

```
$ sudo service mysqld start
```

MySQL が起動しているか確認

```
$ systemctl status mysqld.service
```

MySQL にログイン

```
$ mysql -u root -p
```

初期設定パスワードを変更

```
mysql> set password for 'root'@'localhost' = '********';
```

データベース`wordpress`を作成

```
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
```

ユーザー ID と PW を設定

```
mysql> create user '{ユーザーID}'@'%' identified by '{password}';
```

ユーザーに権限を付与
※権限を付与しないと Wordpress のデータベース接続ができない

```
mysql> grant create on *.* to {ユーザーID};
```

ユーザーが作成されたか確認

```
mysql> select user, host from mysql.user;
```

参考サイト

- [mysql で root の password を変更しようとして Syntax エラー吐かれた](https://qiita.com/k3ntar0/items/22486f0666dc1759e0c1)
- [MySQL8.0 では GRANT でユーザ登録ができなかった話](https://qiita.com/tech31/items/e40a3e73c237c97f94f1)

### WordPress をインストール

- Apache が install されている EC2 インスタンスに SSH ログイン
- amazon-linux-extras リポジトリから php を Web サーバーに install
- php7.4 に対応したライブラリの install
- WordPress を install
- WordPress 本体を Apache から見える場所に配置(/var/www/html/)
- ファイルの所有者を apache に変更
- パブリック IPv4 アドレスで WordPress 管理画面が表示される

`amazon-linux-extras リポジトリ`のソフトウェア一覧を表示

```
$ amazon-linux-extras
```

php7.4 を install

```
$ sudo amazon-linux-extras install -y php7.4
```

php7.4 に対応したライブラリの install

```
$ sudo yum install -y php php-mbstring
```

WordPress を install

```
$ wget https://wordpress.org/latest.tar.gz
```

install したフォルダをを解凍

```
$ tar -xzf latest.tar.gz
```

WordPress 本体を Apache から見える場所に配置(/var/www/html/)

```
$ cd wordpress/
$ sudo cp -r * /var/www/html/
```

ファイルの所有者を apache に変更

```
$ sudo chown apache:apache /var/www/html/ -R
```

参考サイト

- [チュートリアル: Amazon Linux による WordPress ブログのホスティング](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/hosting-wordpress.html)

### WordPress とデータベース接続のエラーでハマった点

WordPress を install して管理画面でデータベース接続ができずにハマりました。その対応策としては mysql のユーザー ID に権限を付与してなかったからです。

#### データベースを使用する権限を付与 part1

```` terminal:エラー文
「ユーザー xxx にはデータベース wordpress を使用できる権限がありますか ?」
```

ユーザーに権限を付与
※権限を付与しないと Wordpress のデータベース接続ができない

```
mysql> grant create on *.* to {ユーザーID};
```

#### データベースを使用する権限を付与 part2

``` terminal:エラー文
WordPress データベースエラー: [SELECT command denied to user '{ユーザーID}'@'{host}' for table 'wp_options']
````

作成したデータベースを書き込めるようにユーザーに権限を付与

```
mysql> grant all on wordpress.\* to '{ユーザーID}'@'{host}';
```

#### Web サーバーから DB サーバーに通信疎通できない場合

``` terminal:エラー文
Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
```

plugin を「caching_sha2_password 」から「mysql_native_password」に変更する

```
mysql> ALTER USER '{ユーザーID}'@'{host}' IDENTIFIED WITH mysql_native_password BY '{password}';
```

参考サイト

- [Sequel Pro で MySQL にログインできない](https://qiita.com/yusuke_dev/items/7f0ca12ced72363f9448)
- [Medial Diagnosis And Treatment](https://mdat.biz/dairynews/2018/10/28/412/)

### EC2 に git をインストール

EC2 Instanceに SSH ログイン

```
$ sudo yum -y update
$ sudo yum install git
```

GitHub のアカウント接続する(下記参考サイトを参照)
`git clone`を実行したディレクトリは`/var/tmp`ディレクトリになります。


### Apatch の DocumentRoot を変更する

- デフォルトでは`/var/www/html`のファイルがページに表示されるので、それを git で pull したファイルを読むように変更する(下記参考サイトを参照)

`/var/www/html`のファイルを`/var/tmp/{リポジトリ名/src}`にコピーする

```
$ cp -pR /var/www/html/* /var/lib/{リポジトリ名/src}/
```

設定ファイル`/etc/httpd/conf/httpd.conf`の書き換え

```
DocumentRoot "/var/tmp/{リポジトリ名/src}"

<Directory "/var/tmp/{リポジトリ名/src}">
```

Apatch を再起動

```
$ sudo systemctl restart httpd
```

作成したフォルダ・ファイルの所有者を apache に変更

```
$ sudo chown apache:apache /var/tmp/{リポジトリ名/src}
```

権限を付与

```
$ sudo chmod 600 /var/tmp/{リポジトリ名/src}
```

参考サイト

- [GitHub ユーザアカウントと GitHub リポジトリ作成 + AWS EC2 から GitHub リポジトリへ push する手順例](https://qiita.com/na0AaooQ/items/61b69580df0aa7e4e875#github%E3%83%A6%E3%83%BC%E3%82%B6%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%A8github%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E4%BD%9C%E6%88%90%E6%89%8B%E9%A0%86)
- [【Apache】DocumentRoot を変更しよう](https://qiita.com/erik_t/items/d8f4746d2dc2992f329e)
- [AWS（EC2）で Redmine と Git、Jenkins を使った WordPress 開発環境の構築と公開を行う](http://doop-web.com/blog/archives/2288)

以上となります。
これでPublic SubnetのEC2 Instanceの`/var/tmp/{リポジトリ名/`で`git pull`すると開発コードが反映されるかと思います。