Dockerとapi blueprint+aglio+drakovを使ってAPI開発を楽にする

## 概要

Web APIの開発をするのにapi blueprintとaglio+drakovを利用してドキュメント作成とモックサーバ立ち上げが簡単にできる環境を構築してみます。

api blueprint
https://apiblueprint.org/

こちらの記事を参考にさせてもらいました。感謝！

API BlueprintとdrakovとdreddでAPIドキュメントを書きつつモックサーバを立ててさらにテストを走らせる
https://arata.hatenadiary.com/entry/2018/03/22/204723


今回構築した環境をGitHubにUPしていますので、ご参考ください。
https://github.com/kai-kou/api-blueprint-use-aglio-darkov


## 環境構築

Docker環境を用意します。

```sh
> mkdir 任意のディレクトリ
> cd 任意のディレクトリ
> touch Dockerfile
> touch docker-compose.yml
```
node.jsが利用できるようにイメージを指定します。
aglioとdrakovもインストールしておきます。

```txt:Dockerfile
FROM node:latest

WORKDIR /projects

RUN npm install -g aglio --unsafe-perm
RUN npm install -g drakov
```

```command``` でaglioとdrakovのそれぞれが起動するようにコマンドを指定しておきます。

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

services:
  aglio:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - "./md:/projects"
    tty: true
    command: aglio --theme-variables slate -i index.md -s -h 0.0.0.0
  drakov:
    build: .
    ports:
      - "3001:3001"
    volumes:
      - "./md:/projects"
    tty: true
    command: drakov -f "**/*.md" --public --watch --p 3001
```

## ドキュメントを用意する

Docker起動前にAPI仕様を記述したファイルを用意しておきます。

```sh
> mkdir md
> touch md/index.md
> touch md/sample.md
```

md/index.mdはAglioで複数mdファイルを取り扱う際に利用します。
aglioで```**/*.md``` と指定できたら良いのですが、Docker-compose.ymlで指定するとうまく起動しませんでした。

```md:md/index.md
<!-- include(sample.md) -->
```

```md:md/sample.md
# GET /message
+ Response 200 (text/plain)

        Hello World!
```

## Dockerコンテナの立ち上げ

準備ができましたので、Dockerコンテナを立ち上げます。

```sh
> docker-compose up -d
```

起動したか確認してみます。

```sh
> docker-compose ps

                 Name                                Command               State           Ports
---------------------------------------------------------------------------------------------------------
api-blueprint-use-aglio-darkov_aglio_1    aglio --theme-variables sl ...   Up      0.0.0.0:3000->3000/tcp
api-blueprint-use-aglio-darkov_drakov_1   drakov -f **/*.md --public ...   Up      0.0.0.0:3001->3001/tcp
```

はい。

それでは、それぞれアクセスしてみます。

```sh:aglio
> open http://localhost:3000/
```

<img width="1244" alt="スクリーンショット 2018-09-03 11.18.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/cc55fb56-2749-08d3-6b00-bf688bb16f8e.png">


```sh:drakov
> curl -v http://localhost:3001/message

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3001 (#0)
> GET /message HTTP/1.1
> Host: localhost:3001
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Drakov API Server
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
< Content-Type: text/plain; charset=utf-8
< Content-Length: 13
< ETag: W/"d-oLZZOWcLwsAQ9NXWoLPk5FkPuSs"
< Date: Mon, 03 Sep 2018 02:19:27 GMT
< Connection: keep-alive
<
Hello World!
* Connection #0 to host localhost left intact
```

はい。それぞれ起動しています。
ログでも確認してみます。

```sh:aglio
> docker-compose logs aglio
aglio_1   | Server started on http://0.0.0.0:3000/
aglio_1   | Rendering index.md
aglio_1   | Socket connected
aglio_1   | Refresh web page in browser
aglio_1   | Socket connected
```

```sh:drakov
> docker-compose logs drakov
drakov_1  |    DRAKOV STOPPED
drakov_1  |    DRAKOV STARTED
drakov_1  | [LOG] Setup Route: GET /message
drakov_1  |    Drakov 1.0.4      Listening on port 3001
drakov_1  |    PUBLIC MODE      running publicly
drakov_1  | [LOG] GET /message
drakov_1  | [MATCHING] by url pattern: /message MATCHED
drakov_1  | [DRAKOV] GET /message
drakov_1  | [LOG] GET /message
drakov_1  | [MATCHING] by url pattern: /message MATCHED
drakov_1  | [DRAKOV] GET /message
```

md/sample.mdの内容を変更してみます。

```md:md/sample.md
# GET /message
+ Response 200 (text/plain)

        Hello World!!!!!
```

変更したらログを確認してみます。

```sh:aglio
> docker-compose logs aglio
aglio_1   | Updated sample.md
aglio_1   | Rendering index.md
aglio_1   | Refresh web page in browser
aglio_1   | Updated sample.md
aglio_1   | Rendering index.md
aglio_1   | Refresh web page in browser
```

```sh:drakov
> docker-compose logs drakov
drakov_1  | [CHANGE] sample.md Restarting 6
drakov_1  |    DRAKOV STOPPED
drakov_1  |    DRAKOV STARTED
drakov_1  | [LOG] Setup Route: GET /message
drakov_1  |    Drakov 1.0.4      Listening on port 3001
drakov_1  |    PUBLIC MODE      running publicly
```
変更を検知してくれていますね。

```sh:aglio
> open http://localhost:3000/
```

<img width="972" alt="スクリーンショット 2018-09-03 11.23.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/5e70122f-17c9-c450-c368-6f3b55dcab5d.png">


```sh:drakov
> curl -v http://localhost:3001/message
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3001 (#0)
> GET /message HTTP/1.1
> Host: localhost:3001
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Drakov API Server
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
< Content-Type: text/plain; charset=utf-8
< Content-Length: 17
< ETag: W/"11-dSdq9EnT5dkGNunArS5pSGaVctI"
< Date: Mon, 03 Sep 2018 02:23:53 GMT
< Connection: keep-alive
<
Hello World!!!!!
* Connection #0 to host localhost left intact
```

それぞれ変更が反映されています。

mdファイルを追加してみます。

```sh
> touch md/sanple2.md
> vi md/sanple2.md
> vi md/index.md
```

```md:md/sanple2.md
# GET /message2
+ Response 200 (text/plain)

        Hello World!!!
```

```md:md/index.md
<!-- include(sample.md) -->
<!-- include(sample2.md) -->
```

追加したら反映されているか確認してみます。

```sh:aglio
> open http://localhost:3000
```

<img width="973" alt="スクリーンショット 2018-09-03 11.26.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/41ac12a5-1819-dcb7-64e8-6d2e61951a8c.png">

```sh:drakov
> curl -v http://localhost:3001/message2
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3001 (#0)
> GET /message2 HTTP/1.1
> Host: localhost:3001
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Drakov API Server
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
< Content-Type: text/plain; charset=utf-8
< Content-Length: 16
< ETag: W/"10-DyKYcjpVzlBcpDK0SJCKLaPPxvE"
< Date: Mon, 03 Sep 2018 02:29:31 GMT
< Connection: keep-alive
<
Hello World!!!!
* Connection #0 to host localhost left intact
```

はい。いい感じです。

たまにファイル更新や追加時にプロセスが落ちてしまうことがありました。
その際には以下コマンドで再起動すると復帰できます。

```sh
> docker-compose start

Starting aglio  ... done
Starting drakov ... done
```

それでは、良きapi blueprint開発ライフを^^