第04章:“観測の実験場”ミニAPIを用意する 🧪🚀
この章で作るのは「わざと遅い」を再現できる、超ミニマムAPIです😊 次章以降のログ🧾・メトリクス📈・ヘルスチェック💚は、この“実験場”にどんどん足していきます!
① 今日のゴール 🎯
- Docker Composeで APIが起動する 📦✅
GET /pingが 常にOKを返す 🏓GET /slowが わざと遅い(待たせる)を再現できる 🐢- ついでに、Windowsから叩いて 動作確認できる 🪟💪
② 図(1枚)🖼️
(ざっくりこういう関係になります👇)
Windowsのブラウザ / curl.exe
|
| http://localhost:3000
v
Dockerコンテナ(Node/TSのミニAPI)
|
| /ping → すぐ返す
| /slow → わざと待ってから返す
v
標準出力ログ(次章以降で育てる🧾)
③ 手を動かす(手順 5〜10個)🛠️
ここでは **Node.jsは安定運用向きのActive LTS(v24系)**をベースに固定します(実務でも安心枠)(Node.js)
TypeScriptは 安定版5.9系でOK(6.0はBetaが出たばかりなので教材は安定版でいきます)(typescriptlang.org)
Composeファイル名は compose.yaml が今どきの推奨です(Docker Documentation)
手順1)フォルダ作成 📁✨
VS Codeで新規フォルダを作って開きます。
例:obs-mini-api
手順2)最低限のファイル構成を作る 🧱
最終的にこうなります👇
obs-mini-api/
compose.yaml
Dockerfile
package.json
tsconfig.json
src/
server.ts
手順3)package.json を用意 📦
プロジェクト直下に package.json を作成:
{
"name": "obs-mini-api",
"private": true,
"type": "module",
"scripts": {
"dev": "tsx watch src/server.ts",
"start": "node dist/server.js",
"build": "tsc -p tsconfig.json"
},
"dependencies": {
"express": "^4.19.2"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^24.0.0",
"tsx": "^4.20.0",
"typescript": "^5.9.0"
}
}
ポイント😊
devは TSをそのまま実行&watch(実験場に最高)build/startは将来「本番っぽい形」に寄せたくなった時用(今は使わなくてもOK)
手順4)tsconfig.json を作る 🧠
{
"compilerOptions": {
"target": "ES2023",
"module": "ESNext",
"moduleResolution": "Bundler",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"skipLibCheck": true
},
"include": ["src"]
}
手順5)ミニAPI本体(/ping と /slow)を書く 🧪
src/server.ts を作成:
import express from "express";
const app = express();
app.use(express.json());
const port = Number(process.env.PORT ?? 3000);
// 🏓 常にOK(観測の“基準点”)
app.get("/ping", (_req, res) => {
res.status(200).json({ ok: true, message: "pong" });
});
// 🐢 わざと遅くする(観測の“再現装置”)
// /slow?ms=1200 みたいに指定できるようにする
app.get("/slow", async (req, res) => {
const raw = String(req.query.ms ?? "");
const requested = Number.parseInt(raw, 10);
// 変な値が来ても暴れないようにガード(超入門の設計ポイント✨)
const ms = Number.isFinite(requested) ? requested : 800;
const clamped = Math.min(Math.max(ms, 0), 10_000); // 0〜10秒に制限
await new Promise<void>((r) => setTimeout(r, clamped));
res.status(200).json({ ok: true, waitedMs: clamped });
});
// 終了時に落ち着いて終わる(後でログにも効く)
const server = app.listen(port, () => {
console.log(`[boot] api listening on http://localhost:${port}`);
});
process.on("SIGTERM", () => {
console.log("[shutdown] SIGTERM received. closing server...");
server.close(() => {
console.log("[shutdown] server closed.");
process.exit(0);
});
});
ここ、地味に大事😎
/slowは 「遅い」症状を確実に作れるので、後のログ・メトリクスでめちゃ便利!clampedは“設計超入門”の第一歩:変な入力が来ても壊れない🛡️
手順6)Dockerfile を作る 🐳
FROM node:24-slim
WORKDIR /app
## 依存関係だけ先に入れる(キャッシュ効いて速い💨)
COPY package.json ./
RUN npm install
## ソースを配置
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
手順7)compose.yaml を作る 🧩
services:
api:
build: .
ports:
- "3000:3000"
environment:
- PORT=3000
# Windowsのバインドマウントでwatchが効きづらい時の保険🔥
- CHOKIDAR_USEPOLLING=true
volumes:
- .:/app
- node_modules:/app/node_modules
volumes:
node_modules: {}
ここも大事ポイント😊
volumesのnode_modulesは「Windows側のnode_modules混入」で地獄になりがちなのを避ける保険🧯CHOKIDAR_USEPOLLING=trueは watchが反応しない時の強い味方
手順8)起動する ▶️
VS Codeのターミナルで:
docker compose up --build
手順9)動作確認する ✅
PowerShellだと curl が別物だったりするので、まずは curl.exe 推奨です🪟👍
curl.exe http://localhost:3000/ping
期待する返り(例):
{"ok":true,"message":"pong"}
次に遅い方:
curl.exe "http://localhost:3000/slow?ms=1200"
期待する返り(例):
{"ok":true,"waitedMs":1200}
手順10)止める ⏹️
Ctrl + C
④ 期待する出力(ログの例)🧾✨
docker compose up すると、だいたいこんな雰囲気が出ます👇
api-1 | [boot] api listening on http://localhost:3000
(ログ編でここを育てます🌱 いまは“出てればOK”)
⑤ つまづきポイント(3つ)🪤
- 3000番がすでに埋まってる 🔥
- エラーっぽかったら、他アプリが使ってる可能性あり
- 対処:
compose.yamlのportsを"3001:3000"に変えて、アクセスもlocalhost:3001にする
- PowerShellの
curlが想定と違う 😵
- 対処:
curl.exeを使う(これが一番ラク)
- コード変更しても反映されない(watchが効かない) 🫠
- まず
CHOKIDAR_USEPOLLING=trueが効いてるか確認 - それでもダメなら、一度止めて
docker compose up --buildで再起動(手早く確実)
⑥ ミニ課題(15分)⏳💪
次のどれか1つやってみてね😊(全部やってもOK!)
- 🧪
/slowに?ms=が無いとき、800じゃなくて200にしてみる - 🎲
/slowを「800ms〜1200msのランダム」にしてみる - 🏓
/ping?name=komiyanmaみたいに渡したら、その名前を返すようにする(入力ガード付きで!)
⑦ AIに投げるプロンプト例(コピペOK)🤖📋
A)“最小で正しい” slow を作りたい
TypeScript + Expressで /slow を作りたいです。
要件:
- /slow?ms=1200 のようにms指定可能
- msが無い/変/負数/大きすぎる時は安全に丸める(0〜10000)
- 返り値は { ok: true, waitedMs: number }
実装例のコードだけ出してください。
B)watchが効かない時の改善案が欲しい
Docker ComposeでWindowsホストのバインドマウント上で tsx watch が反応しないことがあります。
CHOKIDAR_USEPOLLING以外の改善案(環境変数、composeの工夫、フォルダ構成の工夫)を、優先度順に箇条書きで出してください。
C)次章(ログ)に備えて「最低限の1行ログ」を足したい
今のExpress APIに“1行だけ”アクセスログを足したいです。
method, path, status, elapsedMs を1行で出すだけのミドルウェア案をください。
ログはconsole.logのみ、余計な依存は増やさない方向で。
ここまでできたら🎉 あなたは「遅い🐢」をいつでも再現できる“観測の実験場”を手に入れました! 次の章から、このAPIにログ🧾やメトリクス📈を“武装”していきます😆