Swagger EditorとSwagger UIとSwaggerのモックAPIサーバーをdocker-compose化してみた

![07d4ffed-2dbf-4829-ab18-ef27f6877261.png](https://qiita-image-store.s3.amazonaws.com/0/180782/a0e9d8fb-1a65-b496-01cb-99451eb27b1e.png)

## 背景
初投稿です。イレブンナインの松田です。[@matsudachikara2](https://twitter.com/matsudachikara2)
最近、社内でAPIの仕様をどうやって管理、共有していくかを検討してました。そこで、Swaggerを使うのがいい感じらしい！ということを聞き、調査を始めましたが、個々のツールの使い方や導入は出てくるものの、具体的にチームで共有、管理まではどうやってするのかいまいち分かりませんでした。
調べていくと[SwaggerHub](https://swagger.io/tools/swaggerhub/)などのプラットフォームを使うのが一般的みたいでしたが、もっと簡単にSwagger EditorとSwagger UIとSwaggerのモックAPIサーバーを使えたらなということで作ってみました。

## Swaggerとは？
こちらはとても良い記事がすでにありますので、そちらを見ると良いと思います！

* [Swaggerの概要をまとめてみた。](https://qiita.com/gcyata/items/342073fa7607fd4082bd)
* [開発効率を上げる！Swaggerで作るWEB APIモック](https://qiita.com/joooee0000/items/2d5935ec30ec73555eb2)
* [SwaggerでRESTful APIの管理を楽にする](https://qiita.com/disc99/items/37228f5d687ad2969aa2)

## 公開リポジトリ

* [elevennines-inc/swagger-all-in-one-docker-compose](https://github.com/elevennines-inc/swagger-all-in-one-docker-compose)

## swagger-all-in-one-docker-container
### 概要
Swagger EditorとSwagger UIとSwaggerのモックAPIサーバー(openapi: 3.x)を手軽に同時に環境に立ち上げられるようdocker-compose化してみました
もしswagger specを`swagger: "2.0"`形式で書きたい場合は`swagger2.0`branchをお使いください
このコンテナには初期でサンプルのswagger specが入っていて、editor, ui, api, nginxが初期状態で立ち上がり、最初から設定無しで起動出来るようになってます
あとはEditorでopenapi.jsonを保存しコンテナを立ち上げ直すだけで、UIとモックAPIサーバーを最新に更新していくことが出来ます

### 起動方法
```yaml
docker-compose up -d

こんな感じで起動します
docker-compose ps
         Name                       Command               State           Ports
----------------------------------------------------------------------------------------
swagger-api      /usr/local/bin/apisprout / ...   Up      0.0.0.0:8083->8000/tcp
swagger-editor   sh /usr/share/nginx/docker ...   Up      0.0.0.0:8081->8080/tcp
swagger-nginx    nginx -g daemon off;             Up      80/tcp, 0.0.0.0:8084->8084/tcp
swagger-ui       sh /usr/share/nginx/docker ...   Up      0.0.0.0:8082->8080/tcp
```

### 使い方
1. swagger-editorでswagger specを編集
2. swagger specをjson形式でswagger-editorの画面から保存
3. 保存したjsonを`swagger/openapi.json`に移動
4. `docker-compose restart`でswagger-uiとswagger-api(mock server)に変更が反映される
5. もしswagger-editorで外部ファイルを読み込みたい場合は、画面内`File > Import File`から読み込む

### 注意
- `http://localhost:8082/`で参照するとキャッシュで変更が反映されない場合があるので`http://127.0.0.1:8082/`で参照した方が良い(apiも同様)
- swagger-apiの起動に失敗した場合は、`swagger/openapi.json`からモックAPIの立ち上げに失敗した可能性が高いので、`docker logs`などでデバッグし、openapi.jsonを直してから立ち上げ直す
- swagger-apiを他ドメインからアクセスしたい場合は(CORS対策)、swagger-nginx経由でswagger-apiにアクセスする

### swagger-editor
- swagger specを編集出来る
- swagger specはjson, yaml形式などにしてエクスポート出来て、swagger-uiから参照するとドキュメントとして見れる。swagger-apiからjsonを参照するとモックAPIサーバーになる

### swagger-ui
- swagger specをドキュメントとして見れる
- swagger specは環境変数でjsonファイルまたは、API_URLからjsonを参照できる
```
environment:
  SWAGGER_JSON: /openapi.json
  # API_URL: ""
```
- このレポジトリの./swagger/openapi.jsonが参照先になっている

### swagger-api(apisprout)
- 内部的に[apisprout](https://github.com/danielgtaylor/apisprout)を使用しています
- swagger specは`openapi: 3.x`に対応しています
- こちらも./swagger/openapi.jsonが参照先になっている
- ただしapisproutがヘッダーに`Access-Control-Allow-Origin`を付けてくれないので、前段にnginxを置き、ヘッダーを付与してAPIにプロキシしています。(他ドメインからAPIにアクセスできないと不便なので。CORS対策。)

### swagger-nginx
- ヘッダー修正用に配置
- `8084`portでnginx経由でモックAPI(swagger-api)にアクセス出来ます。
- curl等で叩けます

  ```json
  * 例
  curl -i -X GET http://127.0.0.1:8084/pets/1 -H "accept: application/json"

  HTTP/1.1 200 OK
  Server: nginx/1.15.3
  Date: Thu, 04 Oct 2018 07:58:19 GMT
  Content-Type: application/json
  Content-Length: 49
  Connection: keep-alive
  Access-Control-Allow-Origin: *
  Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT, OPTIONS
  Access-Control-Allow-Headers: Origin, Authorization, Accept
  Access-Control-Allow-Credentials: true

  {
    "id": 1,
    "name": "doggie",
    "tag": "dog"
  }
  ```


## 追記
### 2018/08/01
swagger specの記述を`swagger: "2.0"`から`openapi": "3.x"`に変更しました。
理由としては、自社で実際にswagger specを作成、編集してみて`openapi": "3.x"`の方が、圧倒的に書きやすかった為です。
それに合わせてmock apiのコンテナの中身を変更、docker-compose.yml等も修正しました。
注意としては、mock apiのみopenapi": "3.x"記述方式でしか動かなくなっております。
もし`swagger: "2.0"`形式で記述したい場合は`swagger2.0`ブランチを用意したのでそちらからご使用ください。

### 2018/10/04
他ドメインからAPIにアクセスできないと不便なので(CORS対策)、nginxのコンテナを追加しました。
apisproutがヘッダーに`Access-Control-Allow-Origin`
を付けてくれないので、前段にnginxを置き、ヘッダーを付与してAPIにプロキシしています。
`8084`portでnginx経由でモックAPIにアクセス出来ます。
SNSが苦手ということでリンクしませんが、木梨さんというスーパーエンジニアの方にサクッと直してもらいました。 Special Thanks to Kinashi!

```
変更前

$ curl -i -X GET http://127.0.0.1:8083/pets/1 -H "accept: application/json"
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 04 Oct 2018 07:36:15 GMT
Content-Length: 49

{
  "id": 1,
  "name": "doggie",
  "tag": "dog"
}
```
```
変更後

$ curl -i -X GET http://127.0.0.1:8084/pets/1 -H "accept: application/json"
HTTP/1.1 200 OK
Server: nginx/1.15.3
Date: Thu, 04 Oct 2018 07:36:18 GMT
Content-Type: application/json
Content-Length: 49
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, PATCH, DELETE, PUT, OPTIONS
Access-Control-Allow-Headers: Origin, Authorization, Accept
Access-Control-Allow-Credentials: true

{
  "id": 1,
  "name": "doggie",
  "tag": "dog"
}
```