Windows10にDocker Toolboxを利用しWebアプリ開発環境(Apach+PHP, MySQL)を構築

# 背景
Webアプリケーション開発用ローカル環境構築のためプロビジョニングツールとしてVagrantとAnsibleを利用していましたが、Dockerの利便性が高いと感じたのでローカル環境を移行しました。

- 主な移行理由
    1. 起動速度の速さ
    2. メンテのしやすさ


# Webアプリ構成
移行前ローカル開発環境は、仮想イメージとしてCentOSを用い、その上に以下のミドルウェア構成でした。

| Webサーバー | 開発言語 | DB |
|:----------:|:-----------:|:------------:|
| Apache | PHP | MySQL |

上記要件を満たすためdockerコンテナの構成は以下としました。

| コンテナ | ミドルウェア |
|:----------:|:-----------:|:------------:|
| Web | Apache + PHP|
| DB | MySQL |


# 構築手順
1. Docker Toolboxを利用したローカル環境構築に必要なパッケージのインストール
2. docker-compose.ymlの設定
3. Dockerの起動・動作確認
4. PDOを利用したMySQLへの接続確認


## Docker Toolboxを利用したローカル環境構築に必要なパッケージのインストール
1. はじめに[Docker Toolbox](https://www.docker.com/products/docker-toolbox)（Docker環境を簡単に構築するためのパッケージ群）をダウンロード・インストールします。

![sc_docker_install_01.png](https://qiita-image-store.s3.amazonaws.com/0/128800/08792488-75f5-2c16-7cca-1dc54d6b5388.png)
<div style="text-align: center;">Docker Toolboxインストール①</div>

![sc_docker_install_02.png](https://qiita-image-store.s3.amazonaws.com/0/128800/83f6ea9e-9b2f-392f-2427-dc0c768d893b.png)
<div style="text-align: center;">Docker Toolboxインストール②</div>

![sc_docker_install_03.png](https://qiita-image-store.s3.amazonaws.com/0/128800/1f08b6bf-0779-524b-4c1e-e0c9155a6bb1.png)
<div style="text-align: center;">Docker Toolboxインストール③</div>
*「Install VirtualBox with NDIS5 driver[default NDIS6]」はチェック

正常にインストールが完了すると、以下のショートカットが確認できると思います。
![kitematic_icon.png](https://qiita-image-store.s3.amazonaws.com/0/128800/8fdc0083-5ceb-d298-3758-e7fe3d0d1160.png)
GUIでDocker Hub上のコンテナの検索・利用が可能です。* 今回は利用しません。

![docker_quickstart_icon.png](https://qiita-image-store.s3.amazonaws.com/0/128800/3955ab65-8e91-fe45-ca59-23fb4ef70210.png)
dockerコマンド関連を利用できるターミナル（Linuxベース）です。  
2. 「Docker quickstart terminal」を起動します。
しばらくすると以下のような画面が立ち上がります。
![docker_terminal_01.png](https://qiita-image-store.s3.amazonaws.com/0/128800/82d9e19d-91bf-7efa-0c02-7122936ce41f.png)

なおデフォルトで「default」というvirtualマシンが起動します。* 今回はterminal起動時に起動される、ぐらいの認識で大丈夫です。

```
$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.13.1
```

ねんのためdocker関連コマンドが正常に実行できるか確認します。

```
$ docker version
time="2017-03-04T12:23:41+09:00" level=info msg="Unable to use system certificate pool: crypto/x509: system root pool is not available on Windows"
Client:
 Version:      1.13.1
 API version:  1.26
 Go version:   go1.7.5
 Git commit:   092cba3
 Built:        Wed Feb  8 08:47:51 2017
 OS/Arch:      windows/amd64

Server:
 Version:      1.13.1
 API version:  1.26 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   092cba3
 Built:        Wed Feb  8 08:47:51 2017
 OS/Arch:      linux/amd64
 Experimental: false
```
```
$ docker-compose version
docker-compose version 1.11.1, build 7afaa436
docker-py version: 2.0.2
CPython version: 2.7.13
OpenSSL version: OpenSSL 1.0.2j  26 Sep 2016
```
```
$ docker-machine version
docker-machine.exe version 0.9.0, build 15fd4c7
```

Docker Toolboxの構成は、[こちらのサイト](http://devcenter.magellanic-clouds.com/learning/docker-toolbox.html)が分かりやすいです。


## docker-compose.ymlの設定
### フォルダ・ファイル構成
```
./docker/
|-- docker-compose.yml
|-- web
|   |-- Dockerfile
|-- db
|   |-- Dockerfile
|-- html
|   |-- index.php
```

| ファイル名 | 説明 |
|:----------|:-----------|
| docker-compose.yml | Docker Composeの設定 |
| web/Dcokerfile | webコンテナ構成の設定 |
| db/Dcokerfile | dbコンテナ構成の設定 |
| html/index.php | テスト確認用phpファイル |

* docker-compose.ymlの記述に関する詳細な説明は、dockerのドキュメントを参照していただくのが間違いありません。  
[英語版](https://docs.docker.com/compose/)  
[日本語訳](http://docs.docker.jp/compose/)


1. 上記フォルダ・ファイルを作成します。

```
$ mkdir docker
$ cd docker
$ mkdir web db db/init.d html
```
```
$ vim docker-compose.yml
version: "2"

services:

  web:
    build: ./web
    ports:
      - "80:80"
    volumes:
      - ./html/:/var/www/html

  db:
    build: ./db
    ports:
      - "30000:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
```

Webコンテナ（Apache+PHP）は[公式イメージ](https://hub.docker.com/_/php/)を利用しています。
また、インストール済パッケージを更新しvimのインストール及びPDOを利用するためPHPのMySQL拡張モジュールをインストールしています。

```
$ vim web/Dockerfile
FROM php:5.6-apache

RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y", "vim"]
RUN docker-php-ext-install pdo_mysql

EXPOSE 80
```

DBコンテナ（MySQL）も[公式イメージ](https://hub.docker.com/_/mysql/)を利用しています。

```
$ vim db/Dockerfile
FROM mysql:5.7
```
```
$ vim html/index.php
<?php phpinfo();
```

## Dockerコンテナの起動・動作確認
1. Dockerコンテナを起動します。-dオプションをつけ、コンテナをバックグランドで起動します。* 初回のみ各コンテナに対して必要なダウンロード・インストールが流れるため起動に時間がかかります。

```
$ docker-compose up -d
Starting docker_web_1
Starting docker_db_1
```

2. Dockerコンテナが正常起動できたか動作確認します。  
`docker-compose ps`は、起動中のコンテナの一覧を確認することができます。   「docker_db_1」がDBコンテナ、「docker_web_1」がWebコンテナです。
StateがUpと表示され、Portsにて正常にホスト・ゲスト間でポートフォワードされていることが確認できます。

```
$ docker-compose ps
    Name                   Command               State            Ports
--------------------------------------------------------------------------------
docker_db_1    docker-entrypoint.sh mysqld      Up      0.0.0.0:30000->3306/tcp
docker_web_1   docker-php-entrypoint apac ...   Up      0.0.0.0:80->80/tcp
```

次に、ブラウザからindex.phpにアクセスしてみます。
`docker-machine ip`を利用し、ゲストマシンのIPを確認します。

```
$ docker-machine ip
192.168.99.100
```

上記のIPとWebコンテナに割り当てたポートを指定して、`http:192.168.99.100:80/`にブラウザでアクセスします。  
正常にphpinfoが表示されるはずです。
![phpinfo.png](https://qiita-image-store.s3.amazonaws.com/0/128800/b3f072a1-b931-4500-160a-873fa3b6cc69.png)

また、pdoドライバとしてmysqlも追加されているはずです。
![phpinfo_mysql_pdo.png](https://qiita-image-store.s3.amazonaws.com/0/128800/355d7169-00d8-e8c5-e407-262236b039b0.png)

最後に、`docker-compose run <ラベル> bash`コマンドを利用し、各コンテナへログインしてみます。まずはWebコンテナにログインします。

```
$ docker-compose run web bash
root@5d5ae08f8fca:/var/www/html# php -v
PHP 5.6.30 (cli) (built: Feb 28 2017 17:33:47)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
```

index.phpがホスト・ゲスト間で共有されていることも確認できます。

```
$ root@d5d1f56b235b:/var/www/html# ls
index.php
```

DBコンテナへログインします。

```
$ docker-compose run db bash
root@b29d3701f3e1:/# mysql -h db --port 3306 --protocol tcp -u root -ppassword
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.17 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)
```


## PDOを利用したMySQLへの接続確認
PHPでWebコンテナからDBコンテナ（MySQL）に接続し、DBのデータを取得するサンプルです。

まずは、DBコンテナ（MySQL）に接続し、テストデータを用意します。

```
$ docker-compose run db bash
root@b29d3701f3e1:/# mysql -h db --port 3306 --protocol tcp -u root -ppassword

mysql> CREATE DATABASE sample;
Query OK, 1 row affected (0.00 sec)

mysql> CREATE TABLE sample.user(id INT, name VARCHAR(20));
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO sample.user VALUES(1, 'Test1'), (2, 'Test2');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM sample.user;
+------+-------+
| id   | name  |
+------+-------+
|    1 | Test1 |
|    2 | Test2 |
+------+-------+
2 rows in set (0.00 sec)
```

PDOを利用したphpソースファイルを作成します。

```
$ vim html/connection.php
<?php

$dns      = 'mysql:host=db;port=3306;dbname=sample';
$user     = 'root';
$password = 'password';

try {
    $pdo = new PDO($dns, $user, $password);
    echo 'Connection success </br>';

    $sql = 'select * from user';
    foreach ($pdo->query($sql) as $row) {
        echo 'id:' . $row['id'] . '</br>';
        echo 'name:' . $row['name'] . '</br>';
    }
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}
```

ブラウザで、`http://192.168.99.100/connection.php`にアクセスすると、正常にMySQLへ接続できることが確認できます。

![pdo_sample_02.png](https://qiita-image-store.s3.amazonaws.com/0/128800/546e2f3a-6a5a-ef53-e6eb-3683ca40a34a.png)


# 参考にさせていただいた記事
[Windows10にDockerでLAMP環境を構築する](http://qiita.com/kamonamban/items/e0150a2a7a4d28db10c4)
[Docker Composeで手軽に開発環境を構築](http://qiita.com/acro5piano/items/1d907f81afd0fb3a199e)