DockerでConoHaのインスタンスを建てて、KUSANAGI(Wordpress)を導入する

Kobitoでタグいっぱいつけたら403が出て同期できなくてびっくりした(5個までらしい)。
ちなみにMacでやります。

### 各公式サイト一覧
- [Docker](https://docs.docker.com)  
サーバ管理に流行りのツールらしい
- [ConoHa](https://www.conoha.jp/)  
VPSを借りることができる
- [KUSANAGI](https://kusanagi.tokyo/)  
Wordpressを爆速で動かすチューニングがしてあるらしい

## Dockerをインストール
- [Docker公式ドキュメント(英語)](https://docs.docker.com/engine/installation/ "Install Docker _ Docker Documentation")
執筆時の最新バージョンは17.09。

Docker for Mac(macOS) のリンク先へ飛び、Stable channel をダウンロード&インストールする。
Docker for Mac は Docker Toolboxと対応してるっぽい。
だから Docker だけじゃなくて、Docker Compose と Docker Machine もインストールされるっぽい。
インストール後に各バージョンを確認する。

```zsh
$ docker version
Client:
 Version:      17.09.0-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:40:09 2017
 OS/Arch:      darwin/amd64

Server:
 Version:      17.09.0-ce
 API version:  1.32 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:45:38 2017
 OS/Arch:      linux/amd64
 Experimental: true

$ docker-compose version
docker-compose version 1.16.1, build 6d1ac21
docker-py version: 2.5.1
CPython version: 2.7.12
OpenSSL version: OpenSSL 1.0.2j  26 Sep 2016

$ docker-machine version
docker-machine version 0.12.2, build 9371605
```

### ついでにcompletionの設定もしておく
- [Docker公式ドキュメント(英語)](https://docs.docker.com/docker-for-mac/#install-bash-completion "Get started with Docker for Mac _ Docker Documentation")

公式ドキュメントはbash版だったので、zsh版を書いておきます。

```zsh
$ mkdir ~/.zsh/completions
$ cd $_
$ vi ~/.zshenv
fpath=(~/.zsh/completions $fpath)
autoload -Uz compinit && compinit -i
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker.zsh-completion _docker
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-compose.zsh-completion _docker-compose
$ ln -s /Applications/Docker.app/Contents/Resources/etc/docker-machine.zsh-completion _docker-machine
$ exec $SHELL -l
```

## Docker Machineで ConoHaにインスタンスを立てる
- [ConoHaAPI公式ドキュメント](https://www.conoha.jp/docs/ "ConoHa API Index _ ConoHa API")
- [ConoHaでDocker Machineを使う - Qiita](https://qiita.com/hironobu_s/items/db865ca43af8eca9d3ac "ConoHaでDocker Machineを使う - Qiita")

ConoHaのAPIを使用します。
OpenStack準拠のものを公開しているとのことです。
OpenStackってなに。

なので、docker-machineのdriverオプションにはopenstackを使用します。

### [RESTlet Client](https://chrome.google.com/webstore/detail/restlet-client-rest-api-t/aejoelaoggembcahagimdiliamlcdmfm "Restlet Client - REST API Testing - Chrome ウェブストア")
RESTfulなAPIに対してリクエストを送る便利なChrome拡張があるので、これを使ってやります。
Pythonでやりたい？なら[requests](http://docs.python-requests.org/en/master/ "Requests_ HTTP for Humans — Requests 2.18.4 documentation")でいいんじゃないですか？

### まずはトークンを取得
- [トークン発行API](https://www.conoha.jp/docs/identity-post_tokens.html "トークン発行 - Identity API v2.0 _ ConoHa API")

[認証サーバAPIエンドポイント]などはConoHaコントロールパネルのAPI情報のエンドポイントから取得します。

```
url: [認証サーバAPIエンドポイント]
method: POST
headers: Content-Type: application/json
body: {
  "auth": {
    "passwordCredentials": {
      "username": "[APIユーザ名]",
      "password": "[APIパスワード]"
    },
    "tenantId": "[APIテナントID]"
  }
}
```

レスポンス内容が多くて、どれがtokenなのかすぐにわからなかったのでメモ。
> 実際に使用するトークンの文字列は`access.token.id`の値です。
> 引用: https://www.conoha.jp/guide/apitokens.php

### インスタンスの種類を取得
- [VMプラン詳細取得API](https://www.conoha.jp/docs/compute-get_flavors_detail.html "VMプラン詳細取得 - Compute API v2 _ ConoHa API")


`--openstack-image-name`に使います。
インスタンスのスペックなどを設定するためにVMプラン詳細取得をします。

```
url: [VPS APIエンドポイント]/[APIテナントID]/flavors/detail
method: GET
headers:
  X-Auth-Token: [さっき取得したToken]
  tenant_id: [APIテナントID]
```

今回は一番安い`g-512mb`を使います。
(KUSANAGIの推奨メモリは4GBですが...)

### イメージの種類を取得
- [イメージ一覧取得(nova)API](https://www.conoha.jp/docs/compute-get_images_list.html "イメージ一覧取得(nova) - Compute API v2 _ ConoHa API")
(nova)ってなに


`--openstack-image-name`に使います。

```
url: [VPS保存イメージサーバAPIエンドポイント]/v2/[APIテナントID]/images
method: GET
headers:
  X-Auth-Token: [さっき取得したToken]
  tenant_id: [APIテナントID]
```

今回は`vmi-ubuntu-16.04-amd64-unified-20gb`を使います。

### セキュリティグループの取得
- [セキュリティグループ一覧取得API](https://www.conoha.jp/docs/neutron-get_secgroups_list.html "セキュリティグループ一覧取得 - Network API v2.0 _ ConoHa API")
- [ConoHaでセキュリティグループを設定する](https://qiita.com/hironobu_s/items/1bb6a8886ae91bb553c9 "ConoHaでセキュリティグループを設定する - Qiita")

`--openstack-sec-groups`に使います。
こいつを忘れると、VPSの作成はできてもアクセスが一切できなくなります。
ConoHaのサーバ追加のオプション->接続可能ポートに該当する設定のようです。
おそらく`default`, `gncs-ipv4-all`, `gncs-ipv6-all`の3つが帰ってくると思います。

```
url: [ネットワークAPIエンドポイント]/v2.0/security-groups
method: GET
headers:
  X-Auth-Token: [さっき取得したToken]
  tenant_id: [APIテナントID]
```

### インスタンスの作成
[ユーザ名]などはConoHaのAPIに使用したものを使ってください。
`test-kusanagi-rod` は任意の名前を付けてください。
(OS_USERNAMEなどの環境変数は、direnvとか使ってそっちで定義してあげたほうがいいと思います。)

```bash:zsh
$ OS_USERNAME=[ユーザ名] \
  OS_TENANT_ID=[テナントID] \
  OS_PASSWORD=[パスワード] \
  OS_AUTH_URL=[認証サーバAPIエンドポイント] \
  OS_REGION_NAME=[リージョン] \
  docker-machine create \
  --driver openstack \
  --openstack-flavor-name g-512mb \
  --openstack-image-name vmi-ubuntu-16.04-amd64-unified-20gb \
  --openstack-sec-groups "default,gncs-ipv4-all" \
  test-kusanagi-rod
```

うまくいった感じになったら以下のコマンドで確認します。
(通信して状態を取ってきているのか、少し時間がかかることがあります。)

```bash:zsh
% docker-machine ls
NAME                ACTIVE   DRIVER      STATE     URL                         SWARM   DOCKER        ERRORS
test-kusanagi-rod   -        openstack   Running   tcp://aaa.bbb.ccc.ddd:eeee           v17.11.0-ce
```


## docker-composeでKUSANAGIを展開
- [KUSANAGI公式ドキュメント](https://kusanagi.tokyo/cloud/kusanagi-runs-on-docker/ "KUSANAGI Runs on Docker – KUSANAGI")

### GitHubからkusanagi-dockerを取得する
docker-compose.yml ファイルを取得します。

```zsh
$ git clone https://github.com/prime-strategy/kusanagi-docker.git
```

### docker-compose.ymlを設定する
GitHubから取ってきたファイルを元に以下の各コンテナの設定を書きます。

- dataコンテナ
- webコンテナ
- appコンテナ
- dbコンテナ

今回は`busybox`, `nginx`, `mariadb`, `php7`を使います。

#### busybox
変更無しです。

#### nginx
FQDNはdocker-machineで作ったVPSサーバのホスト名を入力してください。

#### mariadb
以下の4つを設定します。
- MYSQL_ROOT_PASSWORD
- MYSQL_USER
- MYSQL_PASSWORD
- MYSQL_DATABASE

#### php7
prime-strategy から提供されているphp7のイメージのphp-gdには、jpegを扱う設定がされていないようなので、新イメージのビルドのためにDockerfileの作成から行います。
とりあえず試してみたいなど、気にならない人は変更無しで大丈夫です。
Dockerfileの作成については長くなりそうなので別記事にします。
#### 12/15追記
記事書きました。
[KUSANAGI RODのphp7でphp-gdのJPEGを有効にする](https://qiita.com/tpywao/items/1243b0311561beaf77d2)

### docker-machineの情報を設定する
docker-machineで作成しておいたインスタンスの情報を環境変数に設定しておきます。
(direnvとか使ってる人はそっちで定義してあげたほうがいいと思います。)

```zsh
$ eval $(docker-machine env test-kusanagi-rod)
```

### docker-composeでdockerコンテナを起動
コマンドの実行はdocker-compose.ymlファイルがあるディレクトリで行なってください。
もしくは -f(--file) オプションで指定してください。

```zsh
$ ls
docker-compose.yml
$ docker-compose -p test-kusanagi-rod up -d
$ docker-compose -p test-kusanagi-rod ps
      Name                    Command               State         Ports
------------------------------------------------------------------------------
kusanagi-data      /bin/sh                          Up
kusanagi-mariadb   /docker-entrypoint.sh mysqld     Up      3306/tcp
kusanagi-nginx     /docker-entrypoint.sh /usr ...   Up      0.0.0.0:80->80/tcp
kusanagi-php7      docker-php-entrypoint php-fpm    Up      9000/tcp
```

#### オプション解説
- `-p(--project-name)`: composeで作成するdockerコンテナの集まりの名前
- `-f(--file)`: docker-compose.ymlを指定することができる  
psの時にも指定しないといけないので注意。
- `-d`: デタッチした状態でUPする(バックグラウンド起動)

### ブラウザでVPSインスタンスにアクセスして確認する
インストールしましょう的な画面が出ればOK！

### WordPress 設定
以下の項目を設定します。

- データベース名: MYSQL_DATABASE に指定した文字列。
- ユーザ名: MYSQL_USER に指定した文字列。
- パスワード: MYSQL_PASSWORD に指定した文字列。
- データベースのホスト名: **kusanagi-php7** のlinksに登録した、mysqlのホスト名。  
公式ドキュメントには kusanagi-nginx に登録したものを使うと書いてあるが、php7に登録した名前が使われるようです。
- テーブル接頭辞: 任意の文字列。

あとはユーザ情報などを入力して完了です。

## 導入完了！
<small>((でもFTPの設定とかしてないからテーマとかプラグインとかのインストールができない))</small>

DockerもWordpressも初心者なので、変な使い方してたりするところもあると思います。
もっと良い使い方があれば教えて頂けると嬉しいです！


## 参考
- [Docker公式ドキュメント(英語)](https://docs.docker.com/ "Docker Documentation")
- [ConoHaAPI公式ドキュメント](https://www.conoha.jp/docs/ "ConoHa API Index _ ConoHa API")
- [ConoHaでDocker Machineを使う - Qiita](https://qiita.com/hironobu_s/items/db865ca43af8eca9d3ac "ConoHaでDocker Machineを使う - Qiita")
- [KUSANAGI公式ドキュメント](https://kusanagi.tokyo/cloud/kusanagi-runs-on-docker/ "KUSANAGI Runs on Docker – KUSANAGI")