先に要点
- Dev Containers は、開発環境をコンテナでそろえて、ローカルPCを汚しにくくするやり方です。中心になるのは devcontainer.json で、どのイメージ・拡張・設定を使うかを定義します。
- 初心者が必ず詰まるのは「Windowsでマウントが遅い」「Linuxで生成ファイルが root 所有になる」「シェルスクリプトが
\rで動かない」の3点です。本文で 現象→原因→確認→回避 の形で先回りします。 - 導入する価値があるラインは数値で見えます。目安は「参加者3人以上」「セットアップ手順がREADMEで10行を超える」「言語ランタイムが2つ以上混ざる」。逆に単発スクリプトや1人開発では uv 等の軽い仮想環境で十分なことが多いです。
- 始め方は、Docker を入れて、既存イメージ + 最小の
devcontainer.jsonで1プロジェクト動かすところから。Windowsならソースを WSL2 側に置くのが速度面の前提条件です。
ローカルで開発していると、このPCには Node.js 18、こっちは Python 3.12、さらに DB も… という感じで、気づいたら手元の環境がかなり散らかります。
しかもチーム開発では 自分のPCでは動くのに、他の人のPCでは動かない がかなり起きやすいです。
この記事では、2026年6月時点で Visual Studio Code の Dev Containers ドキュメント、Improve disk performance ガイド、containers.dev の概要と devcontainer.json リファレンスを確認しながら、Dev Containers とは何か、何が便利なのか、最初の作り方、そして実務で確実に詰まる具体例とその回避策を整理します。
依存管理の比較から見たいなら、uvとは?pip・venv・Poetryとの違いを初心者向けに比較|何ができて何を選ぶべきか解説 もつながりやすいです。
Push や Pull Request ごとの自動テストまでつなげたいなら、GitHub Actionsとは?できること・最初の使い方を初心者向けに解説 もあわせて読むと流れが見えます。
Dev Containersとは何か
Dev Containers は、コンテナを使って開発環境をそろえるための仕組みです。
VS Code の Dev Containers 機能や containers.dev の仕様まわりでよく出てきます。
初心者向けにかなりざっくり言うと、アプリを動かすための開発環境を、手元のOSへ直接いろいろ入れずにコンテナ側へまとめるやり方 です。
そのため、ローカルPCを開発用の依存で汚しにくくなります。ただし「ソースコードまでコンテナに閉じ込める」わけではなく、後述するようにソースは手元に残してマウントで共有するのが既定の動作です。この前提が、後で出てくる「マウントが遅い」「権限でハマる」の根っこになります。
何が便利なのか
チームで環境が揃う
devcontainer.json をリポジトリに入れれば「自分のPCだけ動かない」を減らせます。新メンバーの初日のセットアップが数時間から数十分になります。
作り直しが簡単
コンテナが壊れても Rebuild Container するだけ。ローカルのソースコードはマウント側に残るので消えません。
ローカルPCを汚しにくい
いちばん分かりやすい利点です。Node.js、Python、DBクライアント、OSパッケージなどを全部ローカルへ直接入れなくても、コンテナ側へ寄せられます。今このプロジェクトで必要なもの をコンテナへ閉じ込めるので、別プロジェクトと混ざりません。
チームで環境をそろえやすい
開発で地味につらいのが環境差です。
- macOS では動く
- Windows では詰まる
- Linux ではバージョン違いが出る
- 誰かのローカルだけ設定が増えている
Dev Containers では このプロジェクトはこの環境で開く を定義ファイルで持てるので、チームで揃えやすくなります。
作り直しやすい
ローカルに直接いろいろ入れていると、環境が壊れたときに戻すのが面倒です。Dev Containers なら コンテナを作り直す 発想で戻せます。この「壊れてもやり直しやすい」は実務でかなり効きます。
何でできているのか
中心になるのは次の3つです。
- Docker … コンテナを動かす土台。
- devcontainer.json … 開発環境の設定ファイル。
- Dockerfile や Docker Compose … コンテナの中身や複数サービス構成を定義するときに使う。
つまり Dev Containers は単独の新しいコンテナ技術というより、Docker ベースの開発環境を扱いやすくするための定義と仕組み と考えると分かりやすいです。
devcontainer.json は何をするのか
devcontainer.json は開発環境の入口になる設定ファイルです。たとえば次を書けます。
- どのイメージ / Dockerfile / Docker Compose 構成を使うか
- どの拡張機能を入れるか
- どのポートを開けるか
- コンテナ作成後に何を実行するか(
postCreateCommand)
初心者向けには このプロジェクトをどういう開発環境で開くかを書いた設計メモ と考えると入りやすいです。
最初の作り方はどうするのか
いちばん入りやすいのは、VS Code で既存テンプレートやイメージを使って始めるやり方です。4ステップで動かせます。
手順1: Docker を入れる
まず Docker が必要です。Dev Containers はコンテナ前提なので、ここがないと始まりません。Windowsの場合はこの時点で Docker Desktop の WSL2 バックエンドを有効にしておくのが後の速度問題の予防になります(理由は後述)。
手順2: .devcontainer/devcontainer.json を作る
最小例なら次の形です。
{
"name": "sample-app",
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm",
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint"]
}
}
}
既存イメージで Node.js 開発環境を開く形です。最初は自前 Dockerfile を書かず、イメージ指定だけで十分です。
手順3: VS Code でコンテナとして開く
VS Code で Dev Containers: Reopen in Container を選ぶと、その設定で開発環境が立ち上がります。初回はイメージの取得とビルドが走るため、回線とマシン次第で数分かかります。2回目以降はキャッシュが効いて数十秒に縮みます。
手順4: 必要なら Dockerfile へ広げる
依存が増えたら自前 Dockerfile へ広げます。
FROM mcr.microsoft.com/devcontainers/base:ubuntu
RUN apt-get update && apt-get install -y git curl
そして devcontainer.json 側で参照します。
{
"name": "sample-app",
"build": { "dockerfile": "Dockerfile" }
}
複数サービスがあるときはどうするか
アプリ本体だけでなく DB や Redis も一緒に立てたいことがあります。このときは Docker Compose を使う形が分かりやすいです。アプリ・PostgreSQL・Redis のように複数コンテナが必要なら、Compose でまとめて定義し、devcontainer.json からどの service を開発対象にするか指定します。
ざっくり言うと、単体で足りるなら image / Dockerfile、複数サービスなら Compose、で考えると入りやすいです。
実務で必ず詰まる3つの落とし穴と回避策
ここがこの記事の本題です。Dev Containers は「ソースは手元、実行環境はコンテナ、両者をマウントでつなぐ」という構造のため、その境界で確実にハマります。代表的な3つを 現象→原因→確認→回避 の形でまとめます。
落とし穴1: Windowsでマウントが致命的に遅い
現象: Windows + Docker Desktop で、npm install やテスト実行、ファイル保存時の再ビルドが体感で数倍〜10倍遅い。VS Code のファイル監視(ホットリロード)が効かないこともある。
原因: プロジェクトを C:\Users...(Windows側ファイルシステム)に置いたまま開いていると、ファイルI/Oが Windows ↔ WSL2 の境界を毎回越えます。この /mnt/c 経由のアクセスは Linux ネイティブのファイルシステムより大幅に遅く、ファイル数の多い node_modules や .git で顕著に効きます。
確認手順: コンテナ内ターミナルで pwd を実行し、パスが /mnt/c/... や /workspaces/... でもホスト実体が C: 配下なら遅い構成です。time npm ci を Windows側配置と WSL2側配置で計測すると差がはっきり出ます。
回避:
- 最優先: ソースを WSL2 のLinuxファイルシステムへcloneしてから開く。
\wsl$\Ubuntu\home\you\project配下に置き、VS Code から WSL 経由で開けば、マウントが Linux ネイティブになり速くなります。 node_modulesなど大量の小ファイルだけ名前付きボリュームに逃がす。これは VS Code 公式の Improve disk performance ガイドにある手法です。
"mounts": [
"source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume"
],
"remoteUser": "node",
"postCreateCommand": "sudo chown node node_modules"
- I/Oが重すぎるなら、ソースツリー全体を名前付きボリュームに置く
Clone Repository in Container Volumeを使う。バインドマウントを介さないぶん Windows / macOS で速度が出ます。
"workspaceMount": "source=your-volume-name,target=/workspace,type=volume",
"workspaceFolder": "/workspace"
落とし穴2: Linuxホストで生成ファイルが root 所有になる
現象: Linux(または WSL2 上の Docker Engine)で開発中、コンテナ内で生成したファイルがホストから編集・削除できない。rm しようとすると Permission denied、Git が dubious ownership を出すこともある。
原因: Linux のバインドマウントはホストのUID/GIDをそのまま使います。コンテナ内のユーザーがホストのあなた(多くは UID 1000)と違うUIDだと、生成物の所有者がずれます。とくにコンテナが root(UID 0)で動いていると、生成ファイルは全部 root 所有になります。
確認手順: ホスト側で ls -n して所有UIDを見る。コンテナ内で id を実行し、UID/GIDがホストの id と一致しているか比べます。
回避: devcontainer.json でイメージ・Dockerfile・Compose を参照していれば、Dev Containers はコンテナユーザーのUID/GIDをホストに自動で合わせます(updateRemoteUserUID の既定は有効)。明示するなら非rootユーザーを指定します。
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "vscode"
}
ポイントは、イメージ内にUIDを書き換えてよい一般ユーザーをちょうど1人だけ用意すること。同じUIDのユーザーが複数いるとUID更新に失敗します。すでに root 所有で散らかしてしまったら、コンテナ内で sudo chown -R vscode:vscode /workspaces/プロジェクト名 で一括修正できます。
落とし穴3: Windowsの改行(CRLF)でシェルスクリプトが動かない
現象: Windowsでcloneしたリポジトリの entrypoint.sh や postCreateCommand から呼ぶスクリプトが、コンテナ内で no such file or directory や bad interpreter で落ちる。中身は明らかに存在するのに失敗する。
原因: Windowsの Git は既定で core.autocrlf=true のことが多く、checkout時に改行を CRLF に変換します。Linuxのシェルは行末の \r をパスやインタプリタ名の一部と解釈するため、#!/bin/bash\r が「/bin/bash\r というファイルが無い」と判定されます。Windowsのパス区切り </code> をそのままスクリプトに書いている場合も同様に壊れます。
確認手順: コンテナ内で file entrypoint.sh を実行し、with CRLF line terminators と出たらこれです。cat -A スクリプト で行末に ^M$ が見えても同じ。
回避: 個人設定ではなくリポジトリの .gitattributes で改行を固定するのが確実です(GitHub公式も推奨)。
* text=auto eol=lf
*.sh text eol=lf
これでチームの誰がcloneしても、シェルスクリプトはコンテナ内で LF に揃います。すでに混入していれば git add --renormalize . で正規化できます。応急処置としてコンテナ内で sed -i 's/\r$//' スクリプト でも直りますが、根本対策は .gitattributes です。
どの規模・構成なら導入する価値があるか
「何でも Dev Containers にすればよい」わけではありません。コンテナの起動・ビルド・ディスク使用というコストが常にかかるからです。uv などの軽量な仮想環境との一番の違いは、Dev Containers はOSレベルの依存とサービス群まで丸ごと揃える点にあります。逆に言えば、そこまで要らない規模ではオーバーキルです。判断ラインを数値と条件で示します。
| 条件 | 導入の判断 | 代わりの選択肢 |
|---|---|---|
| 開発者が1〜2人 / 全員同じOS | 不要寄り。環境差が起きにくい | 言語標準の仮想環境(venv + uv 等) |
| 開発者が3人以上 / OSが混在 | 導入価値が高い | —(Dev Containers が有力) |
| READMEのセットアップ手順が10行以内 | 不要寄り | セットアップスクリプト1本 |
| セットアップ手順が10行超 / 30分以上かかる | 導入価値が高い | — |
| 言語ランタイムが1つだけ | 場合による | 仮想環境で足りることが多い |
| 言語ランタイムが2つ以上混在 | 導入価値が高い | — |
| DB / Redis など常駐サービスが必要 | 導入価値が非常に高い(Compose連携) | — |
| 単発スクリプト / 使い捨て検証 | 不要 | その場で実行、または uv run |
ざっくりした目安として、「参加者3人以上」「セットアップ手順がREADMEで10行超」「言語ランタイムが2つ以上、または常駐サービスあり」のうち2つ以上に当てはまるなら導入の損益分岐を超えると考えてよいです。逆に1つも当てはまらない単発作業なら、仮想環境のほうが軽くて速いです。
加えてマシン要件も判断材料です。Docker Desktop はコンテナ稼働中にメモリを数GB単位で確保します。実務で複数サービスを立てるならRAM 16GB以上が快適ラインで、8GBだとブラウザやエディタと取り合って厳しくなります。古い・低メモリのPCしか無いチームでは、導入価値があってもまず Docker Desktop のリソース割り当て調整から入ります。
初心者がハマりやすい考え方
ローカルファイルは消えないが、コンテナは作り直せる
Dev Containers は 作業フォルダが全部コンテナに閉じ込められる と誤解しやすいです。実際はローカル(またはWSL2側)のフォルダをマウントして使う形が既定です。ソースは手元にありつつ、実行環境だけコンテナで揃えるイメージに近いです。だからこそ前述の「マウント速度」「権限」の話が効いてきます。
開発用と本番用の Dockerfile は分ける
開発コンテナに入れた便利ツールやデバッグ設定を、そのまま本番に持ち込むのは安全ではありません。本番用は最小・セキュリティ重視(multi-stage build、非root実行)、開発用はデバッグしやすさ重視、と役割を分けるのが定石です。
よくある誤解
Dev Containers を使えば環境差や不具合が全部消えるわけではありません。実際には Docker の理解、マウント、権限、改行コード、ネットワーク、ボリュームの扱いといった別の見どころが出てきます。本記事の3つの落とし穴は、その代表例です。
もう一つ多いのは ローカルに何も入れなくてよくなる という誤解です。実際には Docker やエディタの準備は必要で、Git や補助ツールの考え方も要ります。
Dev Containersに関するよくある質問
Q. Windowsでとにかく遅いです。最初に試すべきことは?
A. ソースを C: 配下から WSL2 のLinuxファイルシステム(\wsl$...)へ移して開き直すことです。これだけで npm install やテストが体感で数倍速くなることがあります。次に node_modules を名前付きボリュームへ逃がします。詳しくは本文「落とし穴1」を参照。
Q. コンテナで作ったファイルがホストから消せません。
A. Linuxホスト特有の権限ずれです。devcontainer.json に "remoteUser": "vscode" 等を指定し、UID/GIDをホストに合わせます。すでに root 所有なら sudo chown -R vscode:vscode で一括修正。本文「落とし穴2」参照。
Q. シェルスクリプトが「no such file or directory」で落ちます。中身はあるのに。
A. CRLF改行が原因のことがほとんどです。.gitattributes に *.sh text eol=lf を書き、git add --renormalize . で正規化してください。本文「落とし穴3」参照。
Q. uv や venv で足りるのに Dev Containers を使う意味は?
A. ランタイムが1つでサービスも無いなら、多くの場合 uv / venv のほうが軽くて速いです。Dev Containers の価値はOSレベルの依存や DB / Redis などの常駐サービスまで丸ごと揃える点にあります。「導入判断ライン」の表で2つ以上当てはまるかを確認してください。
Q. VS Code 以外でも使える?
A. containers.dev の仕様は VS Code 以外にも開かれており、JetBrains IDEs(IntelliJ、PyCharm 等)、GitHub Codespaces、DevPod などで対応が進んでいます。実装が最も進んでいるのは VS Code です。
Q. Docker Desktop は有料?
A. 個人利用・教育・小規模事業者(従業員250人未満かつ年商1000万ドル未満)は無料、それ以上の規模では有料サブスクが必要です。無料の代替として Colima(macOS)、Rancher Desktop、Podman Desktop も選択肢です。
Q. マシンが重いときの対策は?
A. Docker Desktop のリソース割り当て(CPU・メモリ・ディスク)を調整し、不要なコンテナ・イメージを docker system prune で定期削除、ボリュームマウントを最小限に、拡張機能はコンテナ内で必要なものだけに絞ります。複数サービスを常用するなら RAM 16GB以上が快適ラインです。
まとめ
Dev Containers は、コンテナで開発環境をそろえ、ローカルPCを開発依存で汚しにくくするやり方です。中心は devcontainer.json で、必要に応じて Dockerfile や Docker Compose を組み合わせます。
ただし便利さの裏で、Windowsのマウント速度、Linuxの権限ずれ、CRLF改行という3つの落とし穴は確実に踏みます。本文の 現象→原因→確認→回避 を先に押さえておけば、初日でつまずかずに済みます。導入するかどうかは「参加者3人以上・手順10行超・ランタイム2つ以上または常駐サービスあり」のうち2つ以上を満たすかで判断するのが現実的です。
参考リンク
- VS Code Docs: Developing inside a Container
- VS Code Docs: Create a Dev Container
- VS Code Docs: Improve disk performance
- VS Code Docs: Add a non-root user to a container
- GitHub Docs: Configuring Git to handle line endings
- containers.dev: Overview
- containers.dev: devcontainer.json reference