はじめに
チーム開発で地味に時間を奪うのが、環境差分です。
「Node のバージョンが違う」「ローカルに入ってる CLI が古い」「Mac では動くけど Windows だと…」「インストール手順が README にあるけど、いつの間にかズレてる」。こういう“ややこしさ”は、バグより発見しにくいのに、確実に生産性を落とします。
Docker でアプリを動かすのは一般的になりましたが、実は “開発環境そのもの” まで揃えきれていないケースが多いです。
そこで効いてくるのが Dev Container(VS Code の Development Containers)。
これは「このリポジトリを開くときは、このコンテナを開発環境として使ってね」という宣言を devcontainer.json と Dockerfile / Compose で管理する仕組みです。
- 新しいメンバーが参加 → リポジトリを開くだけで同じ環境が立ち上がる
- CI だけでなく、ローカルの“開発体験”まで統一できる
- 依存ツール(formatter, linter, DB クライアント, Cloud SDK…)もまとめられる
- “プロジェクトの開発環境”がコードとしてレビュー可能になる
この記事では、Dev Container の概念を押さえつつ、実際に Node.js + Postgres の開発環境を Dev Container 化して、VS Code でそのまま開発できるところまでをハンズオンで作ります。
座学
1) Dev Container は何を解決するのか
Dev Container は、ざっくり言うと **「IDE がコンテナに入って開発する」**仕組みです。
正確には VS Code がローカルの UI として動き、プロジェクトのファイル操作・ターミナル・拡張機能の一部を コンテナ側で動かします。
これにより、開発者のPCに以下を“直接”入れなくてもよくなります。
- 言語ランタイム(Node / Python / Go…)
- ビルドツール(make, gcc, java…)
- CLI(psql, awscli, gcloud, terraform…)
- lint/format ツール(eslint, prettier, golangci-lint…)
つまり、README の環境構築手順が“実行可能な形”で /.devcontainer に移るのが Dev Container の価値です。
2) 仕組みの全体像(最低限ここだけ)
Dev Container は主に以下の部品で構成されます。
devcontainer.json:VS Code が参照する設定(どのコンテナで開くか、拡張機能、ポート転送、初期コマンドなど)- Dockerfile または docker-compose.yml:開発環境のコンテナ定義
- (任意)
postCreateCommand/initializeCommand:初回セットアップの自動化 - (任意)
features:よくあるツールを簡単に追加できる仕組み(Git, Node, Docker CLI 等)
ここで重要なのは、Dev Container は「コンテナを立てる」だけではなく、“開発体験(拡張機能やポート転送)”まで含めて設定化できる点です。
3) Dockerfile 方式と Compose 方式、どっちがいい?
どちらも使えます。使い分けの感覚はこうです。
- Dockerfile 方式:単体サービス(アプリだけ)で完結しやすい。軽量。
- Compose 方式:DB や Redis など複数サービスが必要なとき強い。現場はこっちが多い。
今回は “開発環境の統一” の旨味が分かりやすいように、**Compose(アプリ + DB)**でいきます。
4) よく使う devcontainer.json の設定(使い所込み)
service/workspaceFolder:どのサービスに入るか、作業ディレクトリをどこにするかforwardPorts:ホスト側へ転送するポート(Webサーバ、DB、Storybook など)customizations.vscode.extensions:チームで入れる拡張機能を固定化postCreateCommand:初回にnpm ciなどを自動実行remoteUser:root を避ける(権限トラブルやファイル所有者問題を避ける)mounts:キャッシュや SSH キーなどを必要に応じてマウント
特に postCreateCommand は効きます。
「開いた瞬間に依存が入り、すぐ動く」状態を作れるので、オンボーディングが劇的に短くなります。
ハンズオン
目標:このリポジトリを VS Code で開いたら、同じ Node 環境 + Postgres が立ち上がり、即開発できる状態を作る。
0) ディレクトリ構成
プロジェクト直下に以下を作ります。
.
├─ .devcontainer/
│ ├─ devcontainer.json
│ ├─ docker-compose.yml
│ └─ Dockerfile
├─ package.json
├─ server.js
└─ .dockerignore
1) 最小アプリを用意(Node + Express)
package.json
{
"name": "devcontainer-demo",
"version": "1.0.0",
"type": "commonjs",
"scripts": {
"dev": "node server.js"
},
"dependencies": {
"express": "^4.19.2",
"pg": "^8.11.5"
}
}
server.js(DB 接続して / で表示)
const express = require("express");
const { Client } = require("pg");const app = express();app.get("/", async (_req, res) => {
const client = new Client({
host: process.env.PGHOST || "db",
port: Number(process.env.PGPORT || 5432),
user: process.env.PGUSER || "postgres",
password: process.env.PGPASSWORD || "postgres",
database: process.env.PGDATABASE || "app",
}); try {
await client.connect();
const r = await client.query("SELECT NOW() as now");
res.send(`Hello Dev Container! DB time: ${r.rows[0].now}`);
} catch (e) {
res.status(500).send(`DB error: ${e.message}`);
} finally {
await client.end().catch(() => {});
}
});app.listen(3000, () => console.log("listening on :3000"));
.dockerignore
node_modules
.git
.DS_Store
2) 開発用コンテナ(Dockerfile)を作る
.devcontainer/Dockerfile
FROM node:20-bookworm# 開発で使いがちなツール(例)
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
git curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*WORKDIR /workspace
入門としては、ここでは「開発に必要な最低限だけ入れる」方針でOKです。
(このあと Features を使うと、もっと楽に増やせます)
3) Compose で “アプリ + DB” を立てる
.devcontainer/docker-compose.yml
version: "3.9"
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
command: sleep infinity
environment:
PGHOST: db
PGPORT: "5432"
PGUSER: postgres
PGPASSWORD: postgres
PGDATABASE: app
ports:
- "3000:3000"
depends_on:
- db db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/datavolumes:
pgdata:
ポイント:
volumes: ..:/workspaceでソースコードをコンテナに見せるcommand: sleep infinityで VS Code が “開発用シェル”として使える状態にするdbは永続ボリュームpgdataを持たせて再起動でもデータ保持
4) devcontainer.json を書く(VS Code に“開き方”を教える)
.devcontainer/devcontainer.json
{
"name": "DevContainer Demo (Node + Postgres)",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace", "forwardPorts": [3000, 5432], "customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-azuretools.vscode-docker"
],
"settings": {
"editor.formatOnSave": true
}
}
}, "postCreateCommand": "npm ci || npm install",
"remoteUser": "node"
}
ポイント:
service: appにより、VS Code は app コンテナに入るforwardPortsでブラウザアクセスやDB接続がしやすくなるpostCreateCommandで初回セットアップを自動化remoteUser: nodeにより root 運用を避け、ファイル権限トラブルを減らす
5) VS Code で Dev Container を起動
- VS Code でプロジェクトを開く
- コマンドパレット → “Dev Containers: Reopen in Container”
- コンテナが立ち上がったら、VS Code のターミナルで:
npm run dev
ブラウザで http://localhost:3000 にアクセスし、DB時刻が出れば成功です。
6) “統一” が効く瞬間(チームでの使い方)
この状態をリポジトリにコミットすると、チームメンバーはこうなります。
- リポジトリを開く
- “Reopen in Container” を押す
- 依存が自動で入り、DB も立ち、すぐ動く
「環境構築の差分」ではなく「コードの差分」に集中できます。
さらに、customizations.vscode.extensions によって Lint/Format が揃うので、PR のノイズも減ります。
まとめ
Dev Container は Dockerfile を“実行環境のため”に書くのではなく、**開発環境を“共有資産としてコード化する”**ための仕組みです。
devcontainer.jsonで IDE の体験(拡張、ポート、初期セットアップ)まで統一- Compose を使えば、DB/Redis など依存サービスも一緒に揃う
- 新規参加者のオンボーディングが短くなり、環境差分のバグが減る
- 開発環境がレビュー可能になり、いつの間にか手順が壊れる事故を防げる
「README の環境構築が長くなってきた」「個人のPC依存が増えてきた」と感じたら、Dev Container はかなり強い選択肢になります。
コメントを残す