DockerでカンタンWordPress (LAMP)開発環境構築

# こんな方へ最適な記事です
 - Dockerを勉強したい！ウンチクは後にしてまずは動かしてみたい！という方
 - 自身のローカル環境を汚さずにサクッとLAMPの開発/検証環境を構築したい方
 - 知らない人がメンテしまくっているWordPressリソースだけいきなり渡されて、とにかくローカルでイジイジしなきゃいけない方

...つまるところ、2年くらい前の私にウリふたつの方へお送りします。誰かの助けになったら幸いです。

# 事前準備
 - まずはDocker / Docker Composeをインストールしませう
    - Dockerには **Docker for Windows/Mac** と **Docker Toolbox** があります
        - Docker for Windows/Mac
            - [CE (Community Edition)](https://www.docker.com/community-edition#/download) と [EE (Enterprise Edition)](https://www.docker.com/enterprise-edition) があります。個人的に勉強したりであればもちろんCEで。
            - Docker Compose はDocker for Windows/Macと一緒にインストールされます。
        - Docker Toolbox
            - [バージョンの古いWindows/Mac用]((https://docs.docker.com/toolbox/overview/))ですので、2018年現在だと、Windows10 ProやHigh Sierraをお使いの方は Docker for Windows/Mac をインストールするとよいでしょう。苦もなくインストール完了します。
            - Windows7でふんばっている方はDocker Toolbox一択です。Qiitaにもインストール手順の記事がありますのでそちらご確認ください。私は他のツールや設定との兼ね合いで結局インストールできず、Macへ鞍替えしたクチです。
 - Git (GitHub)をざっくりでも知りませう
    - サンプルで使うソースはGitHubに上げましたので、最低でもGitのセットアップくらいは完了しているとよいでしょう。

# 環境
  - サンプルを作成した時点の私の環境を列挙しておきます。大体同じだったらサンプル動くはず。
   - Mac
       - OS Version: High Sierra
       - Docker: CE Version 18.03.1-ce, build 9ee9f40
       - Git: Version 2.15.2 (Apple Git-101.1)
   - Windows
       - OS Version: Windows10 Pro x64
       - Docker: CE Version 18.03.1-ce, build 9ee9f40
       - Git: Version 2.15.1.windows.2

# まずはサンプルを動かしてみる
いざ、以下URLへアクセスし、README.md [How to set up]の1〜6に書いてある通りに動かしてみよう！
https://github.com/terraphic/docker-lamp-wp
英語だ？！問題ない！中学生英語だZ！

- **Step3について**
    - 以下のようなエラーが出た場合

    ```console:
    $ git clone git@github.com:terraphic/docker-lamp-wp.git
    Cloning into 'docker-lamp-wp'...
    git@github.com: Permission denied (publickey).
    fatal: Could not read from remote repository.
    ```

    GithubにSSH Key設定をしていないようです。[SSH Keyの設定をする](https://help.github.com/articles/connecting-to-github-with-ssh/)か、以下のようにhttpsでcloneしましょう

    ```console:
    $ git clone https://github.com/terraphic/docker-lamp-wp.git
    ```

- **Step4について**
    - 単にLAMPの開発/検証環境を構築したい人はもちろんStep4不要です。 app dir配下へ適当にphpファイルなどを置いてみてください
    - WordPressのソースをお持ちでない人は[WordPress公式サイトから最新バージョンをダウンロード](https://ja.wordpress.org/download/)してください
    - wp-config.phpを修正しましょう

    ```php:wp-config.php
    define('DB_NAME', 'wpdb');
    define('DB_USER', 'root');
    define('DB_PASSWORD', 'password');
    define('DB_HOST', 'mysql');
    define('DB_CHARSET', 'utf8');
    ```

動いた方！ばんざーい！動かなかった方！あれれ、なんででしょう... :sweat: 
とりあえず細かく見ていきましょう。

# 細かく見ていく
長いです。
## Docker構成
環境構築用ファイルは6ファイルのみです

```console:
docker-lamp-wp
│
├─ app                 # リソースを格納するDir
│  └─ .gitkeep
│
├─ mysql
│  ├─ Dockerfile       # MySQL用Docker file (2)
│  ├─ my.cnf           # MySQLのConfig file (3)
│  └─ db_dump          # dump fileを格納するDir
│      └─ .gitkeep
│
├─ php
│  ├─ apache2.conf     # ApacheのConfig file (6)
│  ├─ Dockerfile       # php用Docker file (4)
│  └─ php.ini          # phpのini file (5)
│
├─ phpmyadmin
│  └─ sessions         # phpmyadminのsession fileを格納するDir
│      └─ .gitkeep
│
├─ .gitignore
├─ docker-compose.yml  # docker compose file (1)
├─ LICENSE
└─ README.md
```

### docker-compose buildコマンド実行時のファイル参照順
上のDocker構成にカッコで番号を振ってみました。

docker-compose.ymlに仮想環境構築の概要を書き、MySQL, php, phpMyAdminの各イメージの細かな設定は各Docker fileへ書く感じ。phpMyAdminは特に設定することがなかったので、このサンプルにはDocker fileを作らなかっただけです。

## (1) docker-compose.yml
```yml:docker-compose.yml
version: '3'

services:
  mysql:
    build: ./mysql
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=wpdb
    volumes:
      - db:/var/lib/mysql
    ports:
      - '3306:3306'
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=password
    links:
      - mysql
    ports:
      - '8000:80'
    volumes:
      - './phpmyadmin/sessions:/sessions'
  php:
    build: ./php
    volumes:
      - ./app:/var/www/html
    links:
      - mysql
    depends_on:
      - mysql
    ports:
      - '8080:80'
volumes:
  db:

```
- version
    - composeファイルのバージョンを指定します。2018年7月現在、最新バージョンは`'3'`です。
    - マイナーバージョン的立ち位置でファイルフォーマットを指定することも可能です。2018年7月現在、最新ファイルフォーマットは`'3.6'`です。
    - バージョンによって使える項目が異なったりしますので、[公式](https://docs.docker.com/compose/compose-file/compose-versioning/)をチェックしてみてください。
- services
    - コンテナの中にセットするイメージを指定します。今回は３つのイメージを指定しています。
        1. mysql
        2. phpmyadmin
        3. php
    - イメージ名は何でもOKです。各コンテナの用途に合った分かりやすい名前を付けましょう。
    - コンテナという概念に慣れなかった当時は、1composeファイル1イメージと勘違いしており、様々な場面で迷宮に入ることもしばしばでした...
- build
    - 各イメージの細かな設定が書いてあるDockerfileのありかを相対パスで指定しています。
    - phpmyadminは特に設定をすることがなかったので、buildの項目はなく、その代わりにimageという項目があります。
- image
    - [Docker Hub](http://docs.docker.jp/docker-hub/overview.html)に登録されているイメージを指定しています。
    - [phpMyAdmin公式イメージ](https://hub.docker.com/r/phpmyadmin/phpmyadmin/)です。安心の公式。
- environment
    - 環境変数を設定しています。Dockerfile内でも設定できます。
    - mysqlの環境変数はwp-config.phpでセットした`DB_PASSWORD`の値と`DB_NAME`の値ですね。腹落ち。※ちなみにwp-config.phpの`DB_HOST`の値はイメージ名ですよ
    - phpmyadminのPMAから始まる環境変数の詳細は[phpMyAdmin公式 > Environment variables summary](https://hub.docker.com/r/phpmyadmin/phpmyadmin/)を参照してくださいね。
- volumes
    - コンテナの中のデータは、コンテナを削除すると全て消えてしまいます。そこで、この世(ローカルDir)とあの世(コンテナ内Dir)をリンクしています。
    - コロン`:`の左側がこの世、右側があの世です
    - データベースのデータを保持(永続化)する場合は、左側に任意のvolume名をセットし、右側にコンテナのパスをセットします。composeファイルのトップレベル項目にもvolumesがありますが、これはローカルのパーミッションエラーを防ぐための設定です。
        - 参考サイト: [Docker Composeでボリューム作成](https://qiita.com/reflet/items/5c0a488494c7d6904084#%E3%83%91%E3%83%BC%E3%83%9F%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%82%89%E3%81%AA%E3%81%84%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)
- ports
    - 参照イメージ内でデフォルトのポートが決まっているので、変更します。
    - コロン`:`の左側がAfter、右側がBeforeです。
    - phpmyadminとphpのポートが`80`でカブっているので、`8000`と`8080`に変更しました。
    - mysqlは`3306`のままですが、分かりやすくするため記載してます。
- links
    - どのイメージと接続するか設定しています。特にphpmyadminはmysqlと接続しないと意味ないですよね。
- depends_on
    - その名の通り、依存しているイメージを設定しています。
    - ここに書かれたイメージが先に立ち上がります。
    - phpmyadminも依存しているではないか？と思った方。はい、すみません。書き忘れました。けどまぁクライアント補助ツールだし、接続はしているので大勢に影響ないっすよね(っていう言い訳)。

## (2) MySQL用Dockerfile
```dockerfile:./mysql/Dockerfile
FROM mysql:5.7
LABEL maintainer acco

COPY ./my.cnf /etc/mysql/conf.d/
```
- [FROM](http://docs.docker.jp/engine/reference/builder.html#from) 命令
    - [Docker Hub](http://docs.docker.jp/docker-hub/overview.html)に登録されているイメージを指定しています。
    - [Docker Hub公式イメージ](https://hub.docker.com/_/mysql/)です。安心の公式（2回目）。
    - コロン`:`の右側はイメージにセットされているタグです。バージョンがタグになっていることが多く、サンプルはMySQL version 5.7をインストールしています。2018年7月現在、`mysql:latest`と書くと、MySQL version 8.0.11がインストールされます。
- [LABEL](http://docs.docker.jp/engine/reference/builder.html#label) 命令
    - mysqlイメージのメタデータをセットしています。
    - サンプルでは作者名を追加しました。
    - 作者名をセットする`MAINTAINER`という命令もありますが、Docker1.13から`MAINTAINER`の使用が非推奨となったようです。
        - 参考サイト: [1.13以降はMAINTAINERの代わりにLABELを使うようにしよう](https://qiita.com/okisanjp/items/a43068f956d273703ea8)
- [COPY](http://docs.docker.jp/engine/reference/builder.html#copy) 命令
    - その名の通り、この世のファイルをあの世にコピーしています。
    - このイメージのOSはDebianなので、MySQLのクライアント設定をincludeしてくれる`/etc/mysql/conf.d/`へMySQLのConfig fileをコピーしています。
    - この世のファイルはDockerfileと同じディレクトリ配下に置く必要があります。

## (3) MySQLのConfig file
```config:./mysql/my.cnf
[mysqld]
character-set-server=utf8
```
- おなじみMySQLの設定ファイルです。適宜カスタマイズしてくださいね。
    - 参考サイト: [基礎MySQL ~その２~ my.cnf (設定ファイル)](https://qiita.com/yoheiW@github/items/bcbcd11e89bfc7d7f3ff)

## (4) php用Dockerfile
```dockerfile:./php/Dockerfile
FROM php:7.0-apache
LABEL maintainer acco

COPY ./php.ini /usr/local/etc/php
COPY ./apache2.conf /etc/apache2/conf-enabled

RUN apt-get update \
  && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev vim \
  && docker-php-ext-install mysqli pdo_mysql gd

RUN a2enmod rewrite
```
- FROM, LABEL, COPY 命令概要は[(2) MySQL用Dockerfile](#2-mysql用dockerfile)を参照してください。(説明するの飽きてきた...わけではないですよ)
- [FROM](http://docs.docker.jp/engine/reference/builder.html#from) 命令
    - [Docker Hub公式イメージ](https://hub.docker.com/_/php/)です。安心の公式（3回目）。
    - サンプルはphp version 7.0.30をインストールしています。
- [LABEL](http://docs.docker.jp/engine/reference/builder.html#label) 命令
    - 割愛 :wink:
- [COPY](http://docs.docker.jp/engine/reference/builder.html#copy) 命令
    - `7.0-apache`のOSはDebianなので、Apache2のConfig fileのコピー先がちょっと特殊です。
        - 参考サイト: [Apache2 Debian conf どこになにを置けばいいのか](https://qiita.com/hikachan/items/3801c8f1c088817d6d53)
- [RUN](http://docs.docker.jp/engine/reference/builder.html#run) 命令
    - あの世でコマンドを実行しています。
    - `apt-get`
        -  Debian系のパッケージ管理システム'[apt](https://packages.debian.org/ja/jessie/apt)'を使って、必要なパッケージをインストールしています。こちらも適宜カスタマイズしてください。各パッケージの内容は...Google先生に聞いてみよう！
    - `a2enmod`
        - おなじみApache2のモジュール有効化コマンド。サンプルではrewriteを有効にしています。

## (5) phpのini file
```ini:./php/php.ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
[Unix Socket]
pdo_mysql.default_socket = /run/mysqld/mysqld.sock
mysql.default_socket = /run/mysqld/mysqld.sock
mysqli.default_socket = /run/mysqld/mysqld.sock
[Log settings]
log_errors = On
error_log = /dev/stderr
```
- おなじみphpの設定ファイルです。適宜カスタマイズしてくださいね。(既視感あり)
    - 参考サイト: [【PHP7】php.iniの設定](https://kame-no.com/vps/php7_setting.php)

## (6) ApacheのConfig file
```conf:./php/apache2.conf
<Directory "/var/www/html">
    AllowOverride All
</Directory>
```
- Apache2のデフォルトであるドキュメントルートディレクトリ`/var/www/html`配下において.htaccessで制御することを許可しています。
    - 参考サイト: [Apache コア機能](https://httpd.apache.org/docs/2.4/ja/mod/core.html)

# おわりに（感想）
個人としては初めてGitHubへリソースをpushし、Qiitaへ投稿してみました。なぜ最初のお題はDockerにしたかというと、Dockerを使うことによって仕事のストレスが解消され、楽になったからです。
開発環境を構築する時、今まで必ずといっていいほど個々人のPC環境によってトラブルが発生していました。Docker導入後は誰でもすぐ開発着手できるようになりストレス削減、We're so happy!!
てことで熱量高めでこのお題を着手し始めたものの...想像以上に公開までに時間がかかってしまいました。短いスパンでコンスタントに良記事を投稿されている方々に改めて尊敬の念を抱く、そんな平成最後の夏。
自身の理解を深めるために書いたものではありますが、誰かのお役に立つことができたらこれ幸い。そしてこれからも自己研鑽のためにコツコツと投稿していきたいなと思いました。
最後に、たくさんの参考サイトに感謝いたします。

それにしても長い。