Dev ContainersでOpenAPIのAPIドキュメントを作る
本記事では、OpenAPI を利用したAPIドキュメントの管理と、Redocly を活用した視覚的なドキュメント生成について解説します。
RedoclyとOpenAPIについて
OpenAPIとは
OpenAPI はREST APIの仕様を記述するための標準的なフォーマットであり、APIのエンドポイント、リクエスト/レスポンスのデータ構造、認証情報などをYAMLまたはJSONで記述できます。
OpenAPI を活用することで、API のドキュメント生成、コード生成、テスト自動化が容易になります。
Redoclyとは
RedoclyはOpenAPIのドキュメントを視覚的にわかりやすく表示するためのツールです。
静的な API ドキュメントの生成や、ローカルでのプレビューが可能になります。また、VS Code の redocly.openapi-vs-code
拡張機能を使えば、エディタ内で OpenAPI のスキーマ編集を効率的に行えます。
Dev Containers の環境構築
OpenAPIを作るための環境づくりには幾つかの方法がありますが、ローカル環境を汚したくないのでDev Containersを利用します。
OpenAPIドキュメントを開発できるセットアップを行います。
以下の 3 つのファイルについて解説します。
docker-compose.yml
version: '3.8'
services:
node22-openapi:
build: ./web
stdin_open: true
working_dir: '/app'
volumes:
- ../server:/app
tty: true
privileged: true
このファイルでは、Node.js 22 の環境を構築するためのコンテナ node22-openapi
を定義しています。
-
build: ./web
→./web
ディレクトリから Docker イメージをビルドします。 -
stdin_open: true
→ コンテナの標準入力を開いたままにする設定。 -
working_dir: '/app'
→ 作業ディレクトリを/app
に設定。 -
volumes: - ../server:/app
→ ホストの../server
ディレクトリをコンテナの/app
にマウント。 -
tty: true
→ ターミナルを有効化。 -
privileged: true
→ 特権モードで実行(Docker 内で Docker を実行するため)。
devcontainer.json
{
"name": "node22-openapi",
"dockerComposeFile": "docker-compose.yml",
"service": "node22-openapi",
"workspaceFolder": "/app",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"customizations": {
"vscode": {
"extensions": [
"redocly.openapi-vs-code",
"github.copilot",
"github.copilot-labs",
"oderwat.indent-rainbow",
"mhutchie.git-graph",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"vscode-icons-team.vscode-icons",
"stylelint.vscode-stylelint"
],
"settings": {
"eslint.options": {
"extensions": [".js", ".ts"]
},
"eslint.validate": ["typescript", "javascript"],
"editor.codeActionsOnSave": {
"source.organizeImports": "never",
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
"typescript.preferences.importModuleSpecifierEnding": "minimal",
"eslint.format.enable": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.trailingComma": "all",
"prettier.useEditorConfig": false,
"prettier.jsxSingleQuote": true,
"prettier.printWidth": 100,
"prettier.semi": true,
"prettier.singleQuote": true,
"prettier.tabWidth": 2
}
}
}
}
このファイルは Dev Container の設定を定義します。
-
name
: Dev Container の名前。 -
dockerComposeFile
: 使用するdocker-compose.yml
のファイル指定。 -
service
: 開発コンテナとして使用するnode22-openapi
を指定。 -
workspaceFolder
: コンテナ内で作業するディレクトリを/app
に設定。 -
features
:docker-in-docker
を有効化(コンテナ内で Docker を動かすため)。 -
customizations.vscode.extensions
: VS Code にインストールする拡張機能一覧。 -
customizations.vscode.settings
: Prettier, ESLint などのフォーマット設定。
Dockerfile
FROM node:22.14
# openapi-generator-cliを動かすためにjavaが必要
RUN apt update; apt install -y wget software-properties-common apt-transport-https git openjdk-17-jre
RUN npm install -g yml-sorter redoc redoc-cli @openapitools/openapi-generator-cli version-manager
# redocly-cliをインストール(ほかと分けたほうが良さそう)
RUN npm install -g @redocly/cli
# Firebase に deployするため
RUN npm install -g firebase-tools
この Dockerfile は Node.js 22.14 環境をベースに OpenAPI 仕様を処理するためのツールをインストールします。
-
RUN apt update; apt install -y ... openjdk-17-jre
→openapi-generator-cli
の実行に必要な Java をインストール。 -
RUN npm install -g yml-sorter redoc redoc-cli ...
→ OpenAPI のツール群をインストール。 -
RUN npm install -g @redocly/cli
→redocly-cli
を個別にインストール。
sample api
openapi.yaml
リモートコンテナを立ち上げたらサンプルサイトを作ります。
src/openapi.yaml
openapi: 3.1.0
info:
title: Sample API
description: "Sample API description"
version: 0.1.10
servers:
- url: http://api.<your-site>.com/v1
description: 本番サーバー
- url: http://staging-api.<your-site>.com
description: 開発サーバー
paths:
/users:
get:
operationId: get-users
summary: users
description: |
**Markdown記法**が使えます。
security:
- {}
responses:
"200":
description: A JSON array of user names
content:
application/json:
schema:
type: array
items:
type: string
OpenAPI 3.1.0と3.0.3について
OpenAPI 3.1.0 は 2021年2月15日にリリースされましたが、多くのツールは 3.0.3 までにしか対応していないことが多いです。そのため3.0.3を採用しても良いと思います。
操作系やHTML生成など
API ドキュメントの確認やバリデーションには以下のコマンドを使用します。
-
プレビュー
redocly preview-docs src/openapi.yaml
このコマンドを実行すると、ローカルサーバーで API ドキュメントをプレビューできます。
-
バリデーション
openapi-generator-cli validate -i ./src/openapi.yaml
これにより、YAMLのOpenAPI 仕様に準拠しているかチェックできます。
-
HTML生成
HTML生成と更新後の差分比較のため、複数のコマンドをまとめたシェルスクリプトを準備します。build#!/bin/sh OUT=./tmp/openapi/openapi.yaml # YAMLファイルのリンター redocly lint ./src/openapi.yaml # 一つのYAMLファイルにまとめる openapi-generator-cli generate -g openapi-yaml -i ./src/openapi.yaml -o tmp # ソートする yml-sorter -i $OUT -o $OUT npx @redocly/cli build-docs $OUT -o ./dest/index.html
bin/build
ビルドするとindex.htmlが作成され、これを公開するとドキュメントを共有できます。
index.htmlをブラウザなどで確認してください。
差分比較や分割など
POSTメソッドを加える
src/openapi.yaml
paths:
/users:
get:
operationId: get-users
summary: users
description: |
**Markdown記法**が使えます。
security:
- {}
responses:
"200":
description: A JSON array of user names
content:
application/json:
schema:
type: array
items:
type: string
+ post:
+ operationId: post-users
+ summary: users
+ description: |
+ **Markdown記法**が使えます。
+ security:
+ - {}
+ requestBody:
+ content:
+ propertyName:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ example: "John Doe"
+ responses:
+ "200":
+ description: idを返す
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 1
先ほど作成したbuildスクリプトを変更して変更比較ができるようにします。
新build
#!/bin/sh
OUT=./tmp/openapi/openapi.yaml
BACKUP=./tmp/openapi/openapi.yaml.bak
# オプションを解析する
while getopts "s" opt; do
case $opt in
s)
skip_build=true
;;
*)
echo "Usage: $0 [-s] (skip build)"
exit 1
;;
esac
done
# YAMLファイルのリンター
redocly lint ./src/openapi.yaml
# 一つのYAMLファイルにまとめる
openapi-generator-cli generate -g openapi-yaml -i ./src/openapi.yaml -o tmp
# ソートする
yml-sorter -i $OUT -o $OUT
# ビルド処理をスキップする場合、早期終了
if [ "$skip_build" = true ]; then
exit 0 # 正常終了でスクリプトを終了
fi
# ドキュメントをビルドする
npx @redocly/cli build-docs $OUT -o ./dest/index.html
# 比較用ファイルを作成する
cp $OUT $BACKUP
変更点の説明
変更点 | 説明 |
---|---|
-s オプションの追加 |
スクリプト実行時に -s を指定すると、ドキュメントのビルドをスキップできるようになった |
バックアップファイルの作成 |
openapi.yaml のコピーを openapi.yaml.bak として保存 |
OpenAPI ドキュメントの差分比較スクリプト
新しく bin/diff
スクリプトを追加し、変更前後の OpenAPI ドキュメントの差分を取得できるようにしました。
#!/bin/sh
OUT=/tmp/openapi/openapi.yaml
OLD=/tmp/openapi/openapi.yaml.bak
DIFF_MOUNTED=/tmp/openapi/diff.md
DIFF=".$DIFF_MOUNTED"
# 最新の OpenAPI YAML を生成(ビルドはスキップ)
./bin/build -s
pwd
docker run --rm -t \
-v $(pwd)/tmp:/tmp:rw \
openapitools/openapi-diff:latest $OLD $OUT --markdown $DIFF_MOUNTED
cat $DIFF
差分比較してみます。(初回のみDockerの初期化のため時間がかかります。
bin/diff
以下のような出力結果が得られます。
今回は少量なので比較にも困りませんが、大量にある場合はとても役立ちます。
==========================================================================
== API CHANGE LOG ==
==========================================================================
Sample API
--------------------------------------------------------------------------
-- What's New --
--------------------------------------------------------------------------
- POST /users
--------------------------------------------------------------------------
-- Result --
--------------------------------------------------------------------------
API changes are backward compatible
--------------------------------------------------------------------------
#### What's New
---
##### `POST` /users
> users
分割
YAMLの課題として、インデントが深くなると記述しづらくなる点があります。。
OpenAPIは分割することが可能です。
paths:
/users:
$ref: paths/users.yaml
paths/users.yaml
get:
operationId: get-users
summary: users
description: |
**Markdown記法**が使えます。
security:
- {}
responses:
"200":
description: A JSON array of user names
content:
application/json:
schema:
type: array
items:
type: string
post:
operationId: post-users
summary: users
description: |
**Markdown記法**が使えます。
security:
- {}
requestBody:
content:
propertyName:
schema:
type: object
properties:
name:
type: string
example: "John Doe"
responses:
"200":
description: idを返す
content:
application/json:
schema:
type: object
properties:
id:
type: integer
example: 1
更にスキーマを分割し整理するとよりAPI開発が進みます。(次回以降説明予定)
まとめ
この環境を使うことで、Dev Containers内でOpenAPIのAPIドキュメントを作成し、redoc
やredocly-cli
を活用して視覚的に確認することができます。
また、openapi-generator-cli
を用いたコード生成も可能になります。
Dev Containers を利用することで、ローカル環境を汚さずに効率的なAPIドキュメント開発ができます。
template
Discussion