ぼくのかんがえたさいきょうのOpenAPI(Swagger) 仕様の策定環境　その2 docker-composeでのSwagger UI の導入

こちらは前回の記事 [ぼくのかんがえたさいきょうのOpenAPI(Swagger) 仕様の策定環境　その1 redocly(yamlのLINT)の導入](https://qiita.com/chr/items/7a21d65cd38091a82adf) の続きとなります。

記事の背景は[前回の記事](https://qiita.com/chr/items/7a21d65cd38091a82adf)をご参照ください

当記事では、 OpenAPIの定義されたyamlファイルを docker-composeを使ってローカルでSwaggerUIを使ってAPI定義を確認できることを目的としています。

# この記事でわかること
- ~~OpenAPIのyamlファイルのlint方法~~ [前回の記事](https://qiita.com/chr/items/7a21d65cd38091a82adf)をご参考ください
- ~~OpenAPIのyamlファイルへ独自lint(カスタムルール)の追加方法~~ [前回の記事](https://qiita.com/chr/items/7a21d65cd38091a82adf)をご参考ください
- docker-composeを使って swagger uiの構築方法と複数ファイルAPI定義があった場合のdocker-composeの実装方法
- ~~docker-composeを使って OpenAPIの定義からmockserverを起動する方法と ホットリロードの実装方法~~ 別記事にします

--
皆さんはじめまして株式会社クライドでオフショア開発部門の事業部長とフィリピン支社のCEOをしている Matsuo です。

今回、私が取り組んでいるプロジェクトにて、FrontendはNextJS , BackendはJavaで多くのAPIを開発する必要があったため、開発をよりスムーズにし、Frontendはバックエンドの実装を待たずにAPIをコールできるようにするのと、FrontendとBackendでAPIの形式の認識齟齬と実装上の違いが起きないようにするために、OpenAPIの定義を使ってFrontendとBackendで共通のAPI仕様を使って開発できるようにする実装方針を選定しました。
そこで、Swagger UIや LINT、Mockserverなどいくつか構築に手間取った箇所があったため、共有します。

# 前提
複数ファイルのOpenAPIの定義ファイルを持っており、複数ファイルの yamlを切り替えながら使えるSwagger UIを導入しています。
Swagger UIについては[こちら](https://swagger.io/tools/swagger-ui/)をご参考ください。
ざっくりSwagger UIについて説明すると、openapiで定義したyamlの定義を確認したり、実際にAPIのエンドポイントをコールできたりするツールです。

# プロジェクトのファイル環境
私のプロジェクトでは以下ファイル構成で環境を構築しています

```tree
.
├── infra_structure
│   ├── Caddyfile // 別記事にて紹介します
│   ├── CustomPrism.Dockerfile  // 別記事にて紹介します
│   ├── docker-compose.yaml
│   └── start-prism.sh  // 別記事にて紹介します
├── node_modules
├── openapi
│   ├── hoge-api.yaml
│   ├── common
│   │   ├── error-response.yaml
│   │   ├── parameters.yaml
│   │   ├── request-bodies.yaml
│   │   └── schema.yaml
│   ├── fuga-api.yaml
├── package-lock.json
├── package.json
├── plugins
│   ├── custom-lint-rules.js
│   └── rules
│       ├── enum-snake-case.js
│       ├── operation-id-camel-case.js
│       ├── query-param-snake-case.js
│       ├── schema-property-snake-case.js
│       ├── tags-kebab-case.js
│       └── tags-kebab-case.js.gz
├── readme.md
└── redocly.yaml
```

openapi/hoge-api.yamlと、openapi/fuga-api.yamlがメインのOpenAPIの定義ファイルとなり、それぞれがcommon配下のyamlを読み込む構成となっています。

dockerの構成に関するファイルは、 infra_structure配下へ設置しています。

# infra_structure/docker-compose.yaml の定義内容
```yaml:infra_structure/docker-compose.yaml
version: "3"
services:
  proxy:
    image: caddy
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
    ports:
      - "8180:80"
    depends_on:
      - hoge_api
      - fuga_api
      - swagger_ui

  swagger_ui:
    image: swaggerapi/swagger-ui
    volumes:
      - ../openapi:/usr/share/nginx/html/api
    ports:
      - "8181:8080"
    environment:
      URLS:
      >
        [
          {
            url: "api/hoge-api.yaml",
            name: "hoge-api",
          },
          {
            url: "api/fuga-api.yaml",
            name: "fuga-api",
          },
        ]
      PORT: 8080

  hoge_api:
    build:
      context: .
      dockerfile: CustomPrism.Dockerfile
    volumes:
      - ../openapi:/openapi
    command: ["mock -d -p 4010 --host 0.0.0.0 /openapi/hoge-api.yaml"]

  fuga_api:
    build:
      context: .
      dockerfile: CustomPrism.Dockerfile
    volumes:
      - ../openapi:/openapi
    command: ["mock -d -p 4010 --host 0.0.0.0 /openapi/fuga-api.yaml"]

```

※当yamlに出てくるCustomPrism.Dockerfile , caddyについては次の記事にて紹介します。

# 起動コマンド
```sh
cd infra_structure
docker-compose up
```

# ブラウザでの表示
ポート番号：8181を以下箇所にて割り当てているため、URLは `http://localhost:8181/` となります
```yaml:infra_structure/docker-compose.yaml
    ports:
      - "8181:8080"
```

# 設定のポイント
## volumesの設定
```yaml:infra_structure/docker-compose.yaml
    volumes:
      - ../:/usr/share/nginx/html/api
```
openapiの定義等をdockerへマウントさせます。その際、インターネットでアクセスできる場所に定義を設置する必要がありました。
そのため、swagger-uiのドキュメントルートは `/usr/share/nginx/html/` が設定されているため、
`/usr/share/nginx/html/` 配下へマウントするように設定します。

## 複数ファイルのyamlを切り替えれるようにする
enviromentを使って設定することができました。
```yaml:infra_structure/docker-compose.yaml
    environment:
      URLS:
      >
        [
          {
            url: "api/openapi/hoge-api.yaml",
            name: "hoge-api",
          },
          {
            url: "api/openapi/fuga-api.yaml",
            name: "fuga-api",
          },
        ]
      PORT: 8080
```
このように、urlの項目では swagger-uiのドキュメントルートからのパスで書く必要があります。
また、swagger uiの起動するポートを指定し、別途ホストOSとつなげるためにポートフォワーディングする設定のポート番号と合わせる必要があります。

これらenviromentのパラメーターは公式の[Parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)のページを参考に設定しています

## 成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69167/e23b15e3-eff1-9dce-4464-14034c0a72f6.png)

こちらの添付画像のように、swagger uiがローカルで起動でき、Select a definitionより、どのyamlを表示するか選択できるようになりました。

Swagger UIの導入により、Openapiの定義を簡単にブラウザで確認できるようになりました。
尚、DockerのSwagger UIはホットリロードに対応しているため、yamlを変更するたびブラウザ上の定義が自動でリロードされます。

## 現在の課題
`docker-compose up` を実行してから、実際に画面が表示できるようになるまで1分ほど待ちます。これが長いです。
原因は別途調査予定。

## VSCodeのPluginでSwagger UIを表示しない理由
VSCodeで、openapiのyamlを右クリックするだけでswagger uiを表示してくれる便利なプラグインがあります。
[Swagger Viewer](https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer)
こちらでも十分なのですが、別記事にて紹介予定のmockserverとも組み合わせて使いたかった(ローカルのswagger uiからローカルのmockserverをコールできるようにしたかった）こともあり、docker-composeでの導入にしております。

次回、Mockserver(Prism）を当環境へ導入しfakerを使ってモックデータを返却するAPIを構築する記事を作成予定です。