Docker初心者がphp+apache+mysqlの開発・検証環境を構築する

# 経緯
phpを全く知らない人間にphpのossについて検証・調査するようにというお達しが来ました。
ossのシステム要件を見ると、linux系のosの指定、 apache、 mysql、 phpのversionにも色々指定があったので、dockerを使って検証することを決意したのでありました。（dockerの名前だけは知っていたので、やってみたいという気持ちがありました）

# 問題点
社内の人間でdockerを知っている人がほとんどいません。また、osもwindows8.1、 10、 macOSなどなど
いざ開発となっても、問題が起こりそうなにおいがプンプンします


# 目標
1. docker toolbox、 docker for windows、 docker for macでも動作すること
2. とにかくわかりやすいこと。なるべくdocker以外入れない。vagrantとか

1に関してはosの問題があるためです。docker for windowsってwindows8.1駄目です。
2に関しては社内の人間が使えないと意味が無いからです。

（この時点でdocker-syncを使うことを諦めます。そもそも、windows用のdocker-syncはwindows10でないと駄目なようです。）


# とりあえず動くものを作った

### ディレクトリ構造
src以下には検証のソースを全部入れる。
shared以下には、apacheのログやmysqlのログとデータが入る。
oss側で必要なphpのライブラリを有効にするために、php-apacheのイメージを元にDockerFileを作成しています。

```shell-session
$ tree -L 2
.
├── docker-compose.yml
├── shared
│   └── logs
├── src
└── web
    └── DockerFile
```
### DockerFile for web
ossに必要なライブラリを有効にするために作成。linuxの知識がないので一番苦戦した。php-extensionの依存ライブラリってどうやって確認するもんですかね?

```Dockerfile:DockerFile
FROM php:7.0.22-apache

# http://qiita.com/suin/items/3a0361102af83d0b69aa
RUN usermod -u 1000 www-data \
    && groupmod -g 1000 www-data

# HACK: 依存しているライブラリを適当に取ってきている. ココらへんの知識がない...
RUN apt-get update && apt-get install -y zlib1g-dev libmcrypt-dev libicu-dev libxml2-dev libxslt1-dev libfreetype6-dev libjpeg62-turbo-dev libpng12-dev

# ossの依存ライブラリをinstall
RUN docker-php-ext-install -j$(nproc) fileinfo mbstring mysqli pdo_mysql zip soap mcrypt intl xsl

RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/

RUN docker-php-ext-configure hash --with-mhash

RUN docker-php-ext-install -j$(nproc) gd hash

# composerも入れておく
RUN cd /usr/local/bin && \
    curl -sS https://getcomposer.org/installer | php

# apache rewriteを有効に
RUN a2enmod rewrite

# 不必要になったファイルを削除
RUN rm -rf /var/lib/apt/lists/*

# apacheの設定ファイルに追記. ossで設定が必要だったため
RUN echo "<Directory '/var/www/html'>\n    AllowOverride All\n</Directory>" >> /etc/apache2/sites-available/000-default.conf

# php:7.0.22-apacheにあるapacheの起動をそのまま持ってきた
ENTRYPOINT ["docker-php-entrypoint"]
CMD ["apache2-foreground"]

```

### docker-compose.yml
最初はvolume関連の知識がなく、ホストのディレクトリをそのままゲストにマウントした。（アホ）

```yaml:docker-compose.yml
web:
  build: "./web/"
  container_name: "oss_web"
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - "./shared/logs/apache2:/var/log/apache2"
    - "./src:/var/www/html" # ホストのディレクトリをそのままゲストにマウントした
  links:
    - "db"

db:
  image: "mysql:5.7"
  container_name: "oss_db"
  environment: 
    - "MYSQL_ROOT_PASSWORD=password"
    - "MYSQL_DATABASE=oss_dev"
    - "MYSQL_USER=oss_dev_user"
    - "MYSQL_PASSWORD=password"
  ports:
    - "3306:3306"  
  volumes:
    - "./shared/db:/var/lib/mysql" # ホストのディレクトリにDBのデータを保持するようにしている
    - "./shared/logs/mysql:/var/log/mysql"
  # utf-8でDBを初期化したかったけど、正しいか謎
  command: "mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci"

```

### 動作確認
遅い！画面表示完了までに1ページに7sかかります。ページによっては20sかかります。
ホストのマウントしているディレクトリのサイズが大きすぎるのが問題のようです。

```shell-session
$ du -ms ./src/
345     ./src/
```

# 改善
### ディレクトリ構造
ディレクトリ構造に変更はないです

### DockerFile for web
DockerFileに変更はないです

### docker-compose.yml
sftpサーバーのvolumeとwebのvolumeを同一にします。
sftp経由で対象のディレクトリにアップロードします。（phpstormを使用して、同期を取りました）

```yaml:docker-compose.yml
version: "2.1"

# dbとsftpサーバ用のvolumeを定義
volumes:
  oss_db_v:
    driver: local
  oss_sftp_v:
    driver: local

services:
  web:
    build: "./web/"
    container_name: "oss_web"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./shared/logs/apache2:/var/log/apache2" # ログぐらいはホストで見れるように
      - "oss_sftp_v:/var/www/html" # ホストのディレクトリではなく、sftp用のvolumeを使用
    links:
      - "db"

  db:
    image: "mysql:5.7"
    container_name: "oss_db"
    environment: 
      - "MYSQL_ROOT_PASSWORD=password"
      - "MYSQL_DATABASE=oss_dev"
      - "MYSQL_USER=oss_dev_user"
      - "MYSQL_PASSWORD=password"
    ports:
      - "3306:3306"  
    volumes:
      - "oss_db_v:/var/lib/mysql" # dbデータもvolumeで管理するようにした
      - "./shared/logs/mysql:/var/log/mysql" # logぐらいはホストで見れるように
    command: "mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci"
  
  sftp:
    image: "atmoz/sftp"
    container_name: "oss_sftp"
    ports:
      - "2222:22"
    volumes: 
      - "oss_sftp_v:/home/sftp-user/upload"
    command: "sftp-user:sftp:::upload"


```


### 動作確認
画面表示完了までに1ページに2s、20sかかっていた画面は5sになりました。（マシになった...）

# 振り返り
docker-composeで作成したvolumeはコンテナを削除したときに、同時に消えてしまうものと思っていました。なので、永続化ためにわざわざホストのディレクトリをマウントしてました。
windows8.1でも動作することで非常に悩んだんですが、sftpでファイルをアップロードすることにしました。何か他の方法があれば教えていただきたいです。



# 今後の改善点
- phpのライブラリの依存関係で入れているものをちゃんとする
- mysqlのutf-8の設定をちゃんとする