Docker で Node と TypeScript の環境を構築する — TypeScript Tips
ホスト PC に Node.js を入れず、Docker だけで Node 22 + TypeScript の学習環境 を揃えます。ソースはボリュームマウントでホストと共有し、コンテナ内で tsc や tsx を実行する構成です。本番デプロイ用のイメージ最適化は対象外で、ローカル学習に閉じた開発用 です。
参考: Docker Docs — Compose · Node.js — Docker · TypeScript — Compiler Options
目次
- なぜ Docker で学習環境を作るか
- 始める前に
- 全体の流れ
- プロジェクトの骨組み
- Dockerfile
- docker-compose.yml
- TypeScript の初期設定
- 起動と日常の使い方
- よくある失敗
なぜ Docker で学習環境を作るか
チームや複数 PC で学習すると、Node のバージョン差(20 と 22 など)や OS 差で「自分の環境だけ動く」が起きがちです。node:22-alpine のような公式イメージを使えば、同じ Node / npm の組み合わせ を再現しやすくなります。
| メリット | 説明 |
|---|---|
| バージョン固定 | FROM node:22-alpine で Node 22 に揃えられる |
| ホストを汚さない | グローバル npm を増やさない |
| 教材の再現性 | README のコマンドがそのまま通りやすい |
ここで作るのは 対話的にコンテナに入ってコーディングする 形です。docker compose run でシェルを開き、マウントした src/ を編集しながら TypeScript を試します。本番向けのマルチステージビルドや最小イメージ化は別トピックです。
始める前に
- Docker Desktop または Docker Engine + Compose が動いている
- 作業フォルダは空でも、これから作るファイルだけでも可
- パスに日本語やスペースがない方が無難(例:
C:\projects\jsts-learn) - ポートはこの構成では特に不要(CLI 学習のみ)
Windows では WSL2 バックエンドの Docker Desktop を使うと、ボリューム I/O が安定しやすいです。
全体の流れ
flowchart LR A["1. フォルダ作成"] --> B["2. package.json / tsconfig"] B --> C["3. Dockerfile + compose"] C --> D["4. docker compose build"] D --> E["5. コンテナで tsc / tsx"]| 段階 | やること |
|---|---|
| 準備 | package.json と tsconfig.json を書く |
| コンテナ定義 | Dockerfile と docker-compose.yml |
| 初回 | docker compose build → npm run typecheck / start |
| 日常 | ホストで編集し、docker compose run --rm app npm run … で確認 |
| 依存追加後 | コンテナで npm install(必要なら再 build) |
ホストに Node が入っていても、学習時はコンテナ内の node / npm を使う と環境差の練習になりません。
プロジェクトの骨組み
作業ルート(例: jsts-learn/)に次の構成を目指します。
jsts-learn/ Dockerfile docker-compose.yml .dockerignore package.json tsconfig.json src/ index.tspackage.json(最小例)
{ "name": "jsts-learn", "private": true, "type": "module", "scripts": { "typecheck": "tsc --noEmit", "start": "tsx src/index.ts" }, "devDependencies": { "typescript": "^5.7.0", "tsx": "^4.19.0" }}type: module は ES モジュールを使う設定です。tsx は TypeScript をそのまま実行するツールで、tsc --noEmit と組み合わせて使います。
src/index.ts
const greeting: string = "Docker + TypeScript";console.log(greeting);Dockerfile
開発・学習用の Dockerfile です。1 ステージで十分です。
FROM node:22-alpineWORKDIR /appCOPY package.json package-lock.json* ./RUN npm installCOPY . .# デフォルトはシェル待ち(compose から上書きも可)CMD ["sh"]package-lock.json がまだないときは npm install をホストまたは初回 docker compose run 前にコンテナで生成します。学習用なら lock なしでも動きますが、バージョン固定には lock が望ましいです。
docker-compose.yml
ボリュームマウントで ホストのソースをコンテナと共有 します。
services: app: build: . volumes: - .:/app - node_modules:/app/node_modules stdin_open: true tty: true working_dir: /appvolumes: node_modules:| 設定 | 意味 |
|---|---|
.:/app |
カレントをコンテナの /app にマウント |
node_modules 匿名ボリューム |
ホストと Linux コンテナの node_modules 衝突を防ぐ |
stdin_open / tty |
対話シェル用 |
PowerShell でビルドとシェル
cd jsts-learndocker compose builddocker compose run --rm app shコンテナ内:
npm run typechecknpm run start--rm は終了時にコンテナを削除します。学習用途では毎回クリーンな状態にしやすいです。
.dockerignore
node_modulesdist.git不要なコピーを減らし、ビルドを速くします。
TypeScript の初期設定
tsconfig.json(学習用ミニマム)
{ "compilerOptions": { "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", "strict": true, "noEmit": true, "skipLibCheck": true, "rootDir": "src", "outDir": "dist" }, "include": ["src"]}strict: true は型チェックを厳しくするスイッチです(個別オプションの意味は tsconfig.json の公式ドキュメントも参照)。ここでは 型チェックだけ先に通る状態 を作ることが目的です。
起動と日常の使い方
初回は docker compose build でイメージを作り、続けてコンテナ内の npm run で動作確認します。Dockerfile の RUN npm install が初回の依存取得を担い、日常の確認はマウント済みのソースに対して docker compose run --rm app npm run … で行います。
初回セットアップ(推奨手順)
# 1. 作業フォルダに Dockerfile / compose / package.json / tsconfig / src を置く# 2. イメージをビルド(Dockerfile 内の npm install が走る)docker compose build# 3. 動作確認(型チェック → 実行)docker compose run --rm app npm run typecheckdocker compose run --rm app npm run startホストに Node がなく、package-lock.json もまだない場合も、この順で足ります。依存を足したあとは次だけです。
docker compose run --rm app npm install# 必要ならイメージも更新docker compose build日常の型チェック / 実行
docker compose run --rm app npm run typecheckdocker compose run --rm app npm run start期待する結果
typecheckがエラーなく終了(終了コード 0)startでDocker + TypeScriptが表示される
エディタ(VS Code / Cursor)はホストで src/index.ts を編集します。保存した内容はマウント経由でコンテナに即反映されます。型の正否はエディタ表示より npm run typecheck で確認します。
flowchart TB Host["ホスト: エディタで編集"] Mount["ボリューム /app"] Container["コンテナ: npm run typecheck / start"] Host --> Mount --> Containerよくある失敗
| 症状 | 対処 |
|---|---|
docker compose が見つからない |
Docker Desktop を起動。Compose V2 は docker compose(ハイフンなし) |
npm install が遅い / 失敗 |
ネットワーク確認。プロキシ環境は npm の設定が必要な場合あり |
ホストの node_modules が壊れる |
compose の node_modules 匿名ボリュームを確認。ホスト側の node_modules は削除してコンテナで再インストール |
Git Bash でパスが .../Git/app になる |
PowerShell を使うか MSYS_NO_PATHCONV=1 を付ける |
Cannot find module 'tsx' |
コンテナ内で npm install を実行したか確認 |
| ファイル変更が反映されない | 保存先がマウントしたフォルダか確認。別ディレクトリを編集していないか |
| Alpine でネイティブモジュールがビルド失敗 | 学習用パッケージ(typescript, tsx)だけなら通常問題なし。追加パッケージで python3 make g++ が要る場合は Dockerfile に apk add |
| Windows で改行 CRLF の警告 | .gitattributes で * text=auto、またはエディタを LF 保存に |
コンテナを完全に作り直すときは docker compose down -v のあと docker compose build です。-v は匿名ボリュームも消すので、次回は npm install が走ります。