TypeScript + Docker のベストプラクティス|軽量 & 高速な開発環境の作り方【Dockerfile付き】
「TypeScript アプリを Docker に載せたけど、Docker イメージが巨大、ホットリロードが効かない、型推論が崩れる…」 そんな悩み、抱えていませんか?
本記事では、Dockerfile の最適化による「イメージサイズの軽量化」「ビルド時間の短縮」「ホットリロード対応」などのよくある課題を、実務目線で解決します。 さらに、開発用と本番用に分けた Dockerfile の構成や CI/CD を見据えた設計思想も詳しく解説。ChatGPT 活用プロンプト例も併せて紹介します。
よくある TypeScript + Docker の課題とその背景
開発現場でよく見かけるのが以下のような課題です:
-
node_modules
を含んだままの Docker イメージでサイズが1GB超え -
ビルドキャッシュが効かず、毎回
npm install
-
tsconfig.json
の設定ミスでnode_modules
をトランスパイル対象に -
ホットリロードが効かず、毎回コンテナ再起動
これらは、Dockerfile や tsconfig.json の設計不備によって発生することが多いです。
Dockerfile 最適化:よくある失敗と改善例
NGな Dockerfile(キャッシュ効率や軽量化を無視)
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/index.js"]
問題点:
-
COPY . .
が早すぎてキャッシュが効かない -
開発用依存(
devDependencies
)も含まれてしまう -
node_modules
の状態がローカルとずれて不安定に
改善された Dockerfile(multi-stage + 軽量 & セキュア)
# builder ステージ(開発・テスト用)
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# production ステージ(本番用)
FROM node:18-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --only=production
CMD ["node", "dist/index.js"]
改善ポイント:
-
package*.json
を先にコピーし、キャッシュ効率を最大化 -
multi-stage build
で開発用ツールを排除し、本番用を軽量化 -
node:18-slim
により セキュリティと安定性を両立
TypeScript + Docker 設定ファイル例(CI/CD・軽量化対応)
tsconfig.json の一例(最小限で厳格)
{
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
.dockerignore(ビルド軽量化の鍵)
node_modules
dist
.git
Dockerfile
docker-compose.*
docker-compose.dev.yml(ホットリロード対応)
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
- /app/node_modules
command: npm run dev
ports:
- "3000:3000"
TypeScript × Docker:設計の原則と選定のポイント
マルチステージビルドの利点
-
開発環境と本番環境の分離
-
キャッシュを活かした CI/CD 対応
-
最小限の依存で軽量 & セキュアなイメージ構築
ベースイメージ | 特徴 |
---|---|
node:18-alpine |
非常に軽量だが依存で詰まりやすい |
node:18-slim |
やや重いが安定性・互換性に優れる |
ChatGPT プロンプトで効率アップ(実例付き)
「Node.js + TypeScript アプリを multi-stage で Docker 化したいです。
開発用(ホットリロードあり)と本番用に分けた Dockerfile を書いてください。
軽量でセキュアに保ちつつ、npm ci を使ってください。」
このように 設計意図(キャッシュ活用、軽量化、依存の分離)を明確化すると、より実務に使える出力が得られます。
よくある落とし穴と CI/CD 対応の注意点
-
COPY
の順番でキャッシュ効率が劇的に変わる -
ホストとのボリュームマウントが
node_modules
を壊す原因に -
alpine
ベースでglibc
必須のモジュールがビルド失敗する -
CI パイプラインでは builder ステージ内でテスト実行し、本番イメージには成果物のみコピーが推奨
関連記事リンク(内部リンク)
FAQ(よくある質問)
Q1. なぜマルチステージ構成が推奨されるの?
A. 不要な開発依存を削除し、軽量で安全な本番環境を作れるからです。
Q2. Alpine ベースは本当に軽い?
A. 軽量ですが node-gyp
などを使う環境では依存解決が難しいため、最初は slim
ベースがおすすめです。
Q3. TypeScript のテストはどうする?
A. builder ステージ内で npm test
を実行し、テスト通過後に dist だけを本番イメージへ。
Q4. ホットリロードは可能?
A. ts-node-dev
や nodemon
+ volume マウント + docker-compose.dev.yml
で 開発用ホットリロード環境を構築可能です。
Q5. ChatGPT に依頼する際のコツは?
A. 「multi-stage」「production dependencies」「キャッシュ最適化」など、設計思想をプロンプトに含めることが成功の鍵です。
まとめ:TypeScript + Docker の最適解を再確認
-
よくある失敗例と改善済み Dockerfile の比較
-
tsconfig / .dockerignore / Compose 構成の実例
-
設計の背景と軽量・安定性のバランス
-
ChatGPT 活用による自動生成のコツ
-
CI/CD を見据えたベストプラクティス
これらを理解すれば、「動くけど遅い」「重すぎる」Docker 環境から卒業できます。