NGINX Unit 0.1で動かなかったWordPressを最新版をつかってDockerで華麗に動かす

# はじめに
先日リリースされていたNGINX Unitについて、WordPressを動かしたかったです。

先日はNGINX Unitを動かすところまでできていたので、そこからWordPressを動かすようにしました。

[NGINX UnitをDockerで動かす](https://qiita.com/yousan/items/9c5f8c929a00c79d5cee)

# 最新版を拾ってくる
先日試した感じだとUnitではWordPressが動きませんでした。

@seiyakubo さんの記事が参考になりました。バージョン0.1（現行の最新版）だとPOSTが送れないため、殆どのPHPアプリケーションが動かないらしいです。

[NGINX UnitでWordpressを動かしてみたけど動かなかった](https://qiita.com/seiyakubo/items/b188d2e4ba85aa7a5d8a)

最新masterブランチだと動くらしかったので、そちらからソースをコピーしました。

# DockerでNGINX Unitのコンテナを作る
前回のコードからNGINX Unit用のコンテナを作ります。

```yaml:Dockerfile
FROM ubuntu:16.04

RUN apt update -y && \
 apt install -y  emacs-nox zsh mlocate git sudo net-tools build-essential


COPY nginx_signing.key /root/nginx_signing.key
RUN apt-key add /root/nginx_signing.key

RUN echo "deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx\n deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx" >> /etc/apt/sources.list
RUN apt update -y
#RUN apt install -y unit
RUN apt install -y nginx
RUN apt install -y php-dev libphp-embed php7.0-mysql mysql-client

RUN git clone https://github.com/nginx/unit /tmp/unit && \
 cd /tmp/unit && \
 git checkout 8e2fd89634bedd4570a2d3d885c209a0e1d20d62 && \
 ./configure --prefix=/opt/unit && \
 ./configure php && \
 make && \
 make install

RUN apt install -y composer
RUN service nginx start

CMD ["/opt/unit/sbin/unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"]

## 何もしないDockerにするときはこれ
# CMD ["sleep","3600"]
```

この中の`git clone`〜あたりで最新版のNGINX Unitのコードを拾っています。
また`unit`起動時に`--control unix:/var/run/control.unit.sock`オプションを与えることで、UNIXソケットの場所を指定します。
この指定がないと`./configure`で指定される`/opt/unit`辺りにソケットファイルが置かれることになります。
こちらでもかまわないのですが、混乱を避けるため/var/runに指定しておきます。

またNGINX周りのインストールも行っています。
NGINX Unitは単体ではアプリケーションを動かすのみで、HTTPサーバ機能は提供されていません。
その為、リバースプロキシとしてNGINXをインストールしています。

Dockerイメージをビルドします。

```bash
$ docker build --rm ./ -t yousan/nginx-unit
```

このイメージはこちらのものと同様です。

https://hub.docker.com/r/yousan/nginx-unit/


# docker-compose
今回はWordPressを使うことが目的のため、MySQL（MariaDB)も一緒に動かします。
docker-composeを使って両方を起動させます。

```yaml:docker-compose.yml
version: '2'

services:
  nginx-unit:
    image: yousan/nginx-unit
    container_name: nginx-unit
    ports:
      - 8300:8300
    volumes:
      - ./json:/root/json
      - ./run:/var/run
      - ./root:/www/root
      - ./conf/php.ini:/etc/php/7.0/embed/php.ini
      - ./conf/default.conf:/etc/nginx/conf.d/default.conf

  mysql:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: example
    ports:
      - 3306:3306
    volumes:
      - ./mysql:/var/lib/mysql
```

HTTPアクセスをNGINXに接続させるため、ポート番号をバインドしています。
またNGINX、PHPのコンフィグファイル、NGINX Unitの制御用jsonファイル、ドキュメントルートをローカル側で編集させるため、ボリュームをマウントしています。

起動します。

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

![Screen Shot 2017-09-23 at 19.13.15.png](https://qiita-image-store.s3.amazonaws.com/0/47327/186125ff-8d34-5efa-1afd-56d8854091ba.png)

動きましたね。

# コマンドの送信
NGINX UnitではHTTPリクエストを使って起動、設定などを行います。
通常のHTTPリクエストはTCP/IPを利用していますが、NGINX Unitの制御に使用するHTTPリクエストはUNIXソケットファイルを使います。
コマンドでは`curl --unix-socket`で指定される引数で接続が指定されます。

今回はDockerの中でNGINX Unitが起動していますので、このソケットファイルを利用する必要があります。
しかしMacOSのDockerではUNIXソケットファイルを共有することができないため、そのままでは通信することができません。
そこでDockerコンテナの中でcurlコマンドを使い、HTTPリクエストを投げてみます。

先ほどdocker-compose.yamlで指定しておいた`json`ディレクトリには、起動用のJSONファイルを置いてあります。

```json:json/start.json
{
  "listeners": {
    "*:8300": {
      "application": "blogs"
    }
  },
  "applications": {
    "blogs": {
      "type": "php",
      "workers": 20,
      "root": "/www/root",
      "index": "index.php"
    }
  }
}
```

このファイルを使ってHTTPリクエストを送ります。コンテナの内部で`curl`コマンドを動かすため、パスの表記に注意が必要です。

```bash
$ docker-compose exec nginx-unit curl -X PUT -d @/root/json/start.json --unix-socket /run/control.unit.sock http://localhost/

{
	"success": "Reconfiguration done."
}
```

![Screen Shot 2017-09-23 at 19.19.21.png](https://qiita-image-store.s3.amazonaws.com/0/47327/5607f692-68fc-07d9-9800-9030025a2391.png)

うまく動きました。

# コンテナの中から送る方法
もちろんコンテナ内部に入って送ることもできます。
`/bin/bash`でコンテナ内部に入り、先ほどと同じコマンドを送信します。

```bash
$ docker-compose exec nginx-unit /bin/bash
# curl -X PUT -d @/root/json/start.json --unix-socket /run/control.unit.sock http://localhost/
```

# 確認

ブラウザで接続して動作を確認しておきます。
ここでは試験用に`phpinfo()`を表示させています。

```php:root/index.php
<?php phpinfo();
```

http://localhost:8300

![Screen Shot 2017-09-23 at 19.14.48.png](https://qiita-image-store.s3.amazonaws.com/0/47327/efa3e037-c6b5-5ef5-5411-7899e9011758.png)

# WordPressの設定
WordPressの本体はPHPファイルです。
今回は`root`というディレクトリをドキュメントルートにしているため、そちらにコアファイルを設置します。
composerを使ってインストールします。

```json:root/composer.json
{
  "require": {
    "php": ">=5.4",
    "johnpbloch/wordpress": "4.7.5"
  },
  "extra": {
    "wordpress-install-dir": "wp/"
  }
}
```

`composer install`でコアファイルをダウンロード、インストールします。
rootディレクトリはバインドされているため、この`composer`コマンドはローカル側、ホスト側どちらで動かしても良いです。
@Hiraku さんのprestissimoの導入ですとか、そのあたりをローカル側で行っているため、ローカルで動かしました。
[光遅い問題を克服してcomposerを10倍速くした話](http://tech.mercari.com/entry/2016/02/01/164829)

インストールが完了したらMySQLのデータベースを作っておきます。

```bash
$ docker-compose exec mysql mysqladmin create -hlocalhost -uroot -ppassword root_wordpress
```

# 確認
ここまでできたら後は動作確認です。
`wp/`ディレクトリにインストールしているので、そちらを参照します。

http://localhost:8300/wp

初期ユーザなどの設定が完了すれば動きます。

![Screen Shot 2017-09-23 at 19.00.32.png](https://qiita-image-store.s3.amazonaws.com/0/47327/29ac3e18-ed09-ea33-4397-2828363be7b1.png)

お疲れ様です！

# まとめ
NGINX Unitは有料版がでるそうですね。今後はPHP-FPM、HHVMなどを置き換えていくほどのすごいアプリケーションになるのか、なにせNGINX謹製のアプリケーションサーバですからその性能に期待して胸が膨らみます。
数台、数百台の仮想インフラ上にアプリケーションユニットをポコポコならべて並列化させて…、もしくはユニットを単位としてAWSとかで提供されて…、なのかもしれませんね！

あと結局Dockerfileは華麗じゃないので書き直せるといいな。

# 参考
http://hatebu.me/entry/2017/09/08/200539
https://www.nginx.com/blog/introducing-nginx-application-platform/