Mac上でDockerを使ってPHP + Apache + Mroongaのローカル環境を構築する

## 環境
- Mac osx v10.9.5
- Docker v1.10.1
- docker-machine v0.6.0

## やること
- 技術検証用に簡易的な環境をローカルに構築する
- 全文検索を実行できるようにする
- ついでにHTTPS通信できるコンテナイメージをDockerHubから探して使う

## Docker Toolbox のインストール
https://www.docker.com/products/docker-toolbox

## Docker-Machineの作成
コンテナを実行する環境であるDocker-machineを作成する。

```bash:
$ docker-machine create --driver virtualbox inspect
$ docker-machine ls # 起動確認
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
default   -        virtualbox   Stopped                                       Unknown   
inspect   -        virtualbox   Running   tcp://xxx.xxx.xx.xxxx:2376           v1.11.2 
```  

## Docker-Machineの環境変数を設定

```bash:
$ eval $(docker-machine env inspect)
```

## ワークスペースを作成

```bash:
$ mkdir -p $HOME/work/proj/inspect/mysql # MYSQLの設定ファイルを置くディレクトリ
$ mkdir -p $HOME/work/proj/inspect/php # PHPファイルを置くディレクトリ
$ cd $HOME/work/proj/inspect/ # 以下このディレクトリで作業
```

## Mroonga(MySQL)コンテナを起動して設定ファイルをコピーする

```bash:
$ docker run --name mroonga -d groonga/mroonga
$ docker cp mroonga:/etc/my.cnf ./mysql
```

## 全文検索の設定を行う

```bash:
$ vi ./mysql/my.conf
```

下記の行を追加

<pre>
# full text search setting
skip-character-set-client-handshake
mroonga_default_parser=TokenMecab
</pre>

下記の行を変更

<pre>
[client]
default-character-set=utf8
</pre>
    

## PHPコンテナを起動して設定ファイルをコピーする
SSL設定不要なコンテナイメージを利用させて頂いております。

```bash:
$ docker run -p 80:80 -p 443:443 -v /Users/xxx/work/proj/inspect/php:/var/www/html --link mroonga:mroonga --name php -d eboraas/apache-php
$ docker cp php:/etc/php5/apache2/php.ini ./
```

## PHPで日本語を扱えるような設定を行う
いつものmbstringの設定です。下記サイト参考にして日本語を扱える設定をする。
http://www.phpbook.jp/install/phpini/index5.html

```bash:
$ vi ./php.ini
```

<pre>
[mbstring]
; language for internal character representation.
; This affects mb_send_mail() and mbstrig.detect_order.
; http://php.net/mbstring.language
mbstring.language = Japanese

; Use of this INI entry is deprecated, use global internal_encoding instead.
; internal/script encoding.
; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*)
; If empty, default_charset or internal_encoding or iconv.internal_encoding is used.
; The precedence is: default_charset < internal_encoding < iconv.internal_encoding
mbstring.internal_encoding = UTF-8

; Use of this INI entry is deprecated, use global input_encoding instead.
; http input encoding.
; mbstring.encoding_traslation = On is needed to use this setting.
; If empty, default_charset or input_encoding or mbstring.input is used.
; The precedence is: default_charset < intput_encoding < mbsting.http_input
; http://php.net/mbstring.http-input
mbstring.http_input = pass 

; Use of this INI entry is deprecated, use global output_encoding instead.
; http output encoding.
; mb_output_handler must be registered as output buffer to function.
; If empty, default_charset or output_encoding or mbstring.http_output is used.
; The precedence is: default_charset < output_encoding < mbstring.http_output
; To use an output encoding conversion, mbstring's output handler must be set
; otherwise output encoding conversion cannot be performed.
; http://php.net/mbstring.http-output
mbstring.http_output = pass 

; enable automatic encoding translation according to
; mbstring.internal_encoding setting. Input chars are
; converted to internal encoding by setting this to On.
; Note: Do _not_ use automatic encoding translation for
;       portable libs/applications.
; http://php.net/mbstring.encoding-translation
mbstring.encoding_translation = Off

; automatic encoding detection order.
; "auto" detect order is changed according to mbstring.language
; http://php.net/mbstring.detect-order
mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII

; substitute_character used when character cannot be converted
; one from another
; http://php.net/mbstring.substitute-character
mbstring.substitute_character = none

; overload(replace) single byte functions by mbstring functions.
; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(),
; etc. Possible values are 0,1,2,4 or combination of them.
; For example, 7 for overload everything.
; 0: No overload
; 1: Overload mail() function
; 2: Overload str*() functions
; 4: Overload ereg*() functions
; http://php.net/mbstring.func-overload
mbstring.func_overload = 0

; enable strict encoding detection.
; Default: Off
mbstring.strict_detection = Off
</pre>

## 設定ファイルを上書きしてコンテナを立ち上げる
先程つくったコンテナを一旦削除して、新たにコンテナを立ち上げ直す。

```bash:
$ docker rm -f php
$ docker rm -f mroonga
$ docker run -v /Users/xxx/work/proj/inspect/mysql/my.cnf:/etc/my.cnf --name mroonga -d groonga/mroonga
$ docker run -p 80:80 -p 443:443 -v /Users/xxx/work/proj/inspect/php.ini:/etc/php5/apache2/php.ini -v /Users/xxx/work/proj/inspect/php:/var/www/html --link mroonga:mroonga --name php -d eboraas/apache-php
$ docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                                      NAMES
d896dcb83be5        eboraas/apache-php   "/usr/sbin/apache2ctl"   6 seconds ago       Up 4 seconds        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   php
d7e0efe05ecc        groonga/mroonga      "/root/entrypoint.sh"    13 days ago         Up 2 minutes        3306/tcp                                   mroonga
```

## 全文検索用のテストデータを投入する

```bash:
$ docker exec -ti mroonga mysql -u root
```

下記サイトを参考にテスト用テーブルhogeを作成してデータ投入。
http://temog.info/archives/php/centos-php-mroonga.html

以下抜粋
<pre>
use test;

create table hoge ( id int primary key auto_increment, content varchar(255), fulltext index(content)) engine = mroonga default charset utf8;

insert into hoge(content) values("全文検索はめんどうだな");

insert into hoge(content) values("全文検索はほげほげです");

insert into hoge(content) values("全文検索は、はげです");

insert into hoge(content) values("全文検索はバルス");

insert into hoge(content) values("あげあげほげほげ");

select * from hoge where match(content) against("ほげ");

+----+-----------------------------------+
| id | content                           |
+----+-----------------------------------+
|  2 | 全文検索はほげほげです            |
|  5 | あげあげほげほげ                  |
+----+-----------------------------------+
2 rows in set (0.00 sec)
</pre>

## 全文検索用のテストPHPを作成する

```bash:
$ vi ./php/test.php
```

```php:test.php
<meta charset="UTF-8">
<title>テスト</title>
<?php
try{
    $db = new PDO('mysql:host=mroonga;dbname=test;port=3306', 'root');
    $st = $db->query("select * from hoge where match(content) against('ほげ')");
    var_dump($st->fetchAll());
} catch (Exception $e) {
    var_dump($e);
}
```

## 動作確認
全文検索できていればOK!!
https://xxx.xxx.xx.xxx/test.php

## まとめ
- コンテナをつかえば簡単と思いきやいろいろ設定しないといけなかった。ミドルウェアの知識は多少必要。
- Dockerfileやdocker-composeを使って自動化するとなおよい。