VSCode Dev Containersとは

VSCode Dev Containersは、Dockerコンテナ内で完全な開発環境を構築できるVSCode拡張機能です。プロジェクトごとに独立した開発環境をコードとして定義し、チーム全員が同一の環境で開発できます。

従来の開発環境構築では「自分の環境では動く」問題が頻発していました。Dev Containersを使えば、開発環境をコンテナ化し、devcontainer.jsonで宣言的に管理できます。新メンバーの環境構築も、リポジトリをクローンしてコンテナを起動するだけで完了します。

本記事では、VSCode Dev Containersの基本的な使い方から、言語・フレームワーク別のテンプレート、チームでの環境共有まで、実践的な内容を網羅的に解説します。

VSCode Dev Containersのメリット

VSCode Dev Containersを導入することで得られるメリットを整理します。

観点 従来の環境構築 VSCode Dev Containers
環境の再現性 手順書に依存、環境差異が発生 devcontainer.jsonで完全に定義
セットアップ時間 数時間~数日 数分(コンテナ起動のみ)
環境の分離 ローカルに直接インストール プロジェクトごとに完全分離
バージョン管理 手動で管理 Gitで構成ファイルをバージョン管理
クリーンアップ アンインストール作業が煩雑 コンテナ削除で完了

主な活用シーン

VSCode Dev Containersは、以下のような場面で特に効果を発揮します。

  • 複数プロジェクトで異なるバージョンのランタイムを使用する場合
  • チーム全員で同一の開発環境を共有したい場合
  • CIと開発環境の差異を最小化したい場合
  • OSに依存しないクロスプラットフォーム開発を行う場合
  • プルリクエストのレビュー時に隔離された環境で検証したい場合

VSCode Dev Containersの前提条件とインストール

システム要件

VSCode Dev Containersを使用するには、以下の環境が必要です。

コンポーネント Windows macOS Linux
Docker Docker Desktop 2.0以上 Docker Desktop 2.0以上 Docker CE/EE 18.06以上
WSL 2(Windowsのみ) Windows 10 Home以降で必須 - -
RAM(リモートホスト) 1GB以上(推奨2GB以上) 1GB以上(推奨2GB以上) 1GB以上(推奨2GB以上)

インストール手順

VSCode Dev Containersのセットアップは、以下の手順で行います。

  1. Dockerをインストールします
  2. VSCodeをインストールします
  3. Dev Containers拡張機能をインストールします

VSCodeのコマンドパレット(Ctrl+Shift+P)から、拡張機能をインストールすることもできます。

1
code --install-extension ms-vscode-remote.remote-containers

インストール後、ステータスバーの左下にリモート接続アイコンが表示されます。

devcontainer.jsonの基本構成

VSCode Dev Containersの中核となるのがdevcontainer.jsonファイルです。このファイルで開発コンテナの構成を定義します。

配置場所

devcontainer.jsonは以下のいずれかの場所に配置します。

  • .devcontainer/devcontainer.json(推奨)
  • .devcontainer.json(プロジェクトルート)

.devcontainerディレクトリを使用する場合、Dockerfileや追加のスクリプトも同じディレクトリに配置できます。

基本的な構成例

最もシンプルなdevcontainer.jsonは、ベースイメージを指定するだけで作成できます。

1
2
3
4
{
  "name": "Node.js開発環境",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:20"
}

主要プロパティの解説

devcontainer.jsonで使用できる主要なプロパティを解説します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
  // コンテナの表示名
  "name": "プロジェクト名",

  // ベースイメージを直接指定
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",

  // またはDockerfileを使用
  "build": {
    "dockerfile": "Dockerfile",
    "context": "..",
    "args": {
      "VARIANT": "3.11"
    }
  },

  // 追加機能(Features)
  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/github-cli:1": {}
  },

  // ポートフォワーディング
  "forwardPorts": [3000, 5432],

  // VSCode拡張機能と設定
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ],
      "settings": {
        "editor.formatOnSave": true
      }
    }
  },

  // ライフサイクルスクリプト
  "postCreateCommand": "npm install",
  "postStartCommand": "npm run dev",

  // コンテナ内で使用するユーザー
  "remoteUser": "node"
}

Featuresによる機能拡張

Dev Container Featuresは、開発環境に追加のツールやランタイムを簡単にインストールできる仕組みです。Dockerfileを編集することなく、宣言的に機能を追加できます。

Featuresの基本的な使い方

featuresプロパティで追加したい機能を指定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {
      "version": "20"
    },
    "ghcr.io/devcontainers/features/python:1": {
      "version": "3.11"
    },
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  }
}

よく使われるFeatures

開発でよく使用されるFeaturesを紹介します。

Feature 用途 指定方法
Node.js JavaScript/TypeScript開発 ghcr.io/devcontainers/features/node:1
Python Python開発 ghcr.io/devcontainers/features/python:1
Go Go言語開発 ghcr.io/devcontainers/features/go:1
Java Java開発 ghcr.io/devcontainers/features/java:1
Docker-in-Docker コンテナ内でDocker使用 ghcr.io/devcontainers/features/docker-in-docker:2
GitHub CLI gh コマンド ghcr.io/devcontainers/features/github-cli:1
AWS CLI AWSコマンドライン ghcr.io/devcontainers/features/aws-cli:1

利用可能なFeaturesの一覧はcontainers.dev/featuresで確認できます。

デフォルトFeaturesの設定

VSCodeの設定で、すべてのDev Containerに自動的にインストールするFeaturesを指定できます。

1
2
3
4
5
{
  "dev.containers.defaultFeatures": {
    "ghcr.io/devcontainers/features/github-cli:1": {}
  }
}

言語・フレームワーク別テンプレート

実際のプロジェクトで使用できる、言語・フレームワーク別のdevcontainer.jsonテンプレートを紹介します。

Node.js / TypeScript

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "name": "Node.js TypeScript",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:20",
  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {}
  },
  "forwardPorts": [3000],
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss"
      ],
      "settings": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
          "source.fixAll.eslint": "explicit"
        }
      }
    }
  },
  "postCreateCommand": "npm install",
  "remoteUser": "node"
}

Python

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
  "name": "Python 3.11",
  "image": "mcr.microsoft.com/devcontainers/python:3.11",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {}
  },
  "forwardPorts": [8000],
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance",
        "charliermarsh.ruff"
      ],
      "settings": {
        "python.defaultInterpreterPath": "/usr/local/bin/python",
        "python.languageServer": "Pylance",
        "[python]": {
          "editor.defaultFormatter": "charliermarsh.ruff",
          "editor.formatOnSave": true
        }
      }
    }
  },
  "postCreateCommand": "pip install -r requirements.txt",
  "remoteUser": "vscode"
}

Java / Spring Boot

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
  "name": "Java Spring Boot",
  "image": "mcr.microsoft.com/devcontainers/java:21",
  "features": {
    "ghcr.io/devcontainers/features/java:1": {
      "version": "21",
      "installMaven": true,
      "installGradle": true
    }
  },
  "forwardPorts": [8080],
  "customizations": {
    "vscode": {
      "extensions": [
        "vscjava.vscode-java-pack",
        "vmware.vscode-spring-boot",
        "vscjava.vscode-spring-initializr"
      ],
      "settings": {
        "java.server.launchMode": "Standard",
        "java.configuration.updateBuildConfiguration": "automatic"
      }
    }
  },
  "postCreateCommand": "./mvnw dependency:resolve",
  "remoteUser": "vscode"
}

Go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
  "name": "Go",
  "image": "mcr.microsoft.com/devcontainers/go:1.22",
  "features": {
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },
  "forwardPorts": [8080],
  "customizations": {
    "vscode": {
      "extensions": [
        "golang.go"
      ],
      "settings": {
        "go.toolsManagement.autoUpdate": true,
        "go.useLanguageServer": true,
        "[go]": {
          "editor.formatOnSave": true,
          "editor.codeActionsOnSave": {
            "source.organizeImports": "explicit"
          }
        }
      }
    }
  },
  "postCreateCommand": "go mod download",
  "remoteUser": "vscode"
}

React / Next.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "name": "React Next.js",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:20",
  "forwardPorts": [3000],
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss",
        "formulahendry.auto-rename-tag",
        "dsznajder.es7-react-js-snippets"
      ],
      "settings": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true,
        "emmet.includeLanguages": {
          "javascript": "javascriptreact",
          "typescript": "typescriptreact"
        }
      }
    }
  },
  "postCreateCommand": "npm install",
  "remoteUser": "node"
}

Dockerfileを使用したカスタム環境

ベースイメージだけでは要件を満たせない場合、Dockerfileを使用してカスタム環境を構築できます。

Dockerfileの作成

.devcontainer/Dockerfileを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
FROM mcr.microsoft.com/devcontainers/base:ubuntu

# 追加パッケージのインストール
RUN apt-get update && apt-get install -y \
    curl \
    git \
    vim \
    && rm -rf /var/lib/apt/lists/*

# カスタムツールのインストール
RUN curl -fsSL https://example.com/install.sh | bash

# 作業ディレクトリの設定
WORKDIR /workspace

devcontainer.jsonでDockerfileを参照

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "name": "カスタム環境",
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },
  "features": {
    "ghcr.io/devcontainers/features/node:1": {}
  },
  "customizations": {
    "vscode": {
      "extensions": ["dbaeumer.vscode-eslint"]
    }
  }
}

ビルド引数の使用

Dockerfileにビルド引数を渡すことで、柔軟な構成が可能です。

1
2
ARG PYTHON_VERSION=3.11
FROM mcr.microsoft.com/devcontainers/python:${PYTHON_VERSION}
1
2
3
4
5
6
7
8
{
  "build": {
    "dockerfile": "Dockerfile",
    "args": {
      "PYTHON_VERSION": "3.12"
    }
  }
}

Docker Composeとの連携

複数のサービス(データベース、キャッシュなど)が必要な場合、Docker Composeと連携できます。

docker-compose.ymlの作成

.devcontainer/docker-compose.ymlを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
services:
  app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
    volumes:
      - ..:/workspace:cached
    command: sleep infinity
    depends_on:
      - db
      - redis

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: devuser
      POSTGRES_PASSWORD: devpass
      POSTGRES_DB: devdb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: redis:7
    ports:
      - "6379:6379"

volumes:
  postgres-data:

devcontainer.jsonでDocker Composeを参照

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "name": "Full Stack with DB",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "forwardPorts": [3000, 5432, 6379],
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "cweijan.vscode-database-client2"
      ]
    }
  },
  "postCreateCommand": "npm install"
}

ライフサイクルスクリプト

Dev Containersは、コンテナのライフサイクルに応じてスクリプトを実行できます。

スクリプトの種類と実行タイミング

flowchart LR
    A[コンテナ作成] --> B[onCreateCommand]
    B --> C[updateContentCommand]
    C --> D[postCreateCommand]
    D --> E[postStartCommand]
    E --> F[postAttachCommand]
    
    style A fill:#e1f5fe
    style B fill:#fff3e0
    style C fill:#fff3e0
    style D fill:#fff3e0
    style E fill:#fff3e0
    style F fill:#e8f5e9
スクリプト 実行タイミング 主な用途
onCreateCommand コンテナ作成直後(1回のみ) 初期セットアップ
updateContentCommand コンテナ作成後、ソース更新時 依存関係の更新
postCreateCommand コンテナ作成完了後(1回のみ) 依存関係インストール
postStartCommand コンテナ起動ごと 開発サーバー起動
postAttachCommand VSCode接続ごと ユーザー固有の設定

実践的な設定例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "name": "開発環境",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:20",
  
  "onCreateCommand": "echo 'コンテナを作成しています...'",
  
  "postCreateCommand": {
    "install": "npm install",
    "setup": "npm run setup",
    "db": "npm run db:migrate"
  },
  
  "postStartCommand": "npm run dev",
  
  "postAttachCommand": "git config --global user.name '${localEnv:GIT_USER_NAME}'"
}

複数コマンドの実行

複数のコマンドを実行する場合、オブジェクト形式で並列実行が可能です。

1
2
3
4
5
6
7
{
  "postCreateCommand": {
    "npm": "npm install",
    "pip": "pip install -r requirements.txt",
    "setup": "chmod +x scripts/setup.sh && ./scripts/setup.sh"
  }
}

環境変数の管理

Dev Containersで環境変数を設定する方法は複数あります。

devcontainer.jsonで直接指定

1
2
3
4
5
6
7
8
9
{
  "containerEnv": {
    "NODE_ENV": "development",
    "API_URL": "http://localhost:3000"
  },
  "remoteEnv": {
    "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
  }
}

containerEnvはコンテナ全体に、remoteEnvはVSCodeのリモートセッションに適用されます。

.envファイルの使用

Docker Composeを使用する場合、.envファイルを読み込めます。

1
2
3
4
5
6
# docker-compose.yml
services:
  app:
    env_file:
      - .env
      - .env.local

ローカル環境変数の参照

ローカルマシンの環境変数をコンテナ内で使用できます。

1
2
3
4
5
6
{
  "remoteEnv": {
    "GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}",
    "AWS_ACCESS_KEY_ID": "${localEnv:AWS_ACCESS_KEY_ID}"
  }
}

既存プロジェクトへの導入手順

既存のプロジェクトにVSCode Dev Containersを導入する手順を解説します。

手順1: Dev Containers設定ファイルの追加

コマンドパレット(Ctrl+Shift+P)から「Dev Containers: Add Dev Container Configuration Files…」を実行します。

プロジェクトの言語やフレームワークに応じたテンプレートを選択できます。

手順2: devcontainer.jsonのカスタマイズ

生成されたdevcontainer.jsonをプロジェクトの要件に合わせてカスタマイズします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "name": "既存プロジェクト",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:20",
  "features": {
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },
  "forwardPorts": [3000, 5432],
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ]
    }
  },
  "postCreateCommand": "npm install"
}

手順3: コンテナで開く

コマンドパレットから「Dev Containers: Reopen in Container」を実行します。初回はコンテナのビルドが行われるため、数分かかる場合があります。

手順4: 動作確認とチューニング

コンテナ内で開発タスクを実行し、必要に応じて設定を調整します。

1
2
3
4
5
6
7
8
# 依存関係のインストール確認
npm install

# 開発サーバーの起動確認
npm run dev

# テストの実行確認
npm test

導入時のチェックリスト

既存プロジェクトへの導入時に確認すべき項目です。

  • 必要なランタイム・ツールがコンテナ内で利用可能か
  • ポートフォワーディングが正しく設定されているか
  • 依存関係のインストールコマンドが正しいか
  • Git認証情報が引き継がれているか
  • ファイルの変更がリアルタイムで反映されるか

チームでの環境共有

Dev Containersの最大のメリットは、チーム全員が同一の開発環境を共有できることです。

リポジトリへのコミット

.devcontainerディレクトリをリポジトリにコミットします。

.devcontainer/
├── devcontainer.json
├── Dockerfile        # カスタムイメージが必要な場合
└── docker-compose.yml # 複数サービスが必要な場合

.gitignoreの設定

ローカル固有の設定ファイルは.gitignoreに追加します。

# Dev Container local overrides
.devcontainer/.env.local
.devcontainer/local-settings.json

チーム向けドキュメント

READMEに Dev Containers の使用方法を記載します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
## 開発環境のセットアップ

### 前提条件
- Docker Desktop
- VSCode + Dev Containers拡張機能

### セットアップ手順
1. リポジトリをクローン
2. VSCodeでフォルダを開く
3. 「Reopen in Container」を選択
4. コンテナのビルド完了を待つ

開発サーバーは`npm run dev`で起動し、http://localhost:3000 でアクセスできます。

プリビルドイメージの活用

チームの生産性を向上させるため、ビルド済みのイメージを使用できます。

1
2
3
{
  "image": "ghcr.io/your-org/your-project-devcontainer:latest"
}

GitHub ActionsでDev Containerイメージを自動ビルドし、GitHub Container Registryにプッシュすることで、チームメンバーのコンテナ起動時間を短縮できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# .github/workflows/devcontainer-build.yml
name: Build Dev Container

on:
  push:
    branches: [main]
    paths:
      - '.devcontainer/**'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Build and push
        uses: devcontainers/ci@v0.3
        with:
          imageName: ghcr.io/${{ github.repository }}/devcontainer
          push: always

トラブルシューティング

VSCode Dev Containersで発生しやすい問題と解決方法を紹介します。

コンテナのビルドが失敗する

ビルドログを確認し、エラーの原因を特定します。

1
2
3
4
5
# ログの確認
# VSCode: コマンドパレット > Dev Containers: Show Container Log

# キャッシュをクリアして再ビルド
# VSCode: コマンドパレット > Dev Containers: Rebuild Container Without Cache

ポートフォワーディングが機能しない

forwardPortsの設定を確認し、コンテナ内でアプリケーションが正しいポートでリッスンしているか確認します。

1
2
3
4
5
6
7
8
9
{
  "forwardPorts": [3000],
  "portsAttributes": {
    "3000": {
      "label": "Application",
      "onAutoForward": "notify"
    }
  }
}

拡張機能がインストールされない

拡張機能IDが正しいか確認し、コンテナを再ビルドします。

1
2
3
4
5
6
7
8
9
{
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint"
      ]
    }
  }
}

拡張機能IDは、VSCodeの拡張機能ページで確認できます。

Git認証情報が引き継がれない

SSH鍵を使用している場合、SSH Agentが正しく設定されているか確認します。

1
2
3
# ローカルでSSH Agentを起動
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

HTTPSを使用している場合、Git Credential Managerが設定されていれば自動的に引き継がれます。

ファイルの変更が反映されない

Windowsでボリュームマウントのパフォーマンスが低い場合、WSL 2バックエンドを使用していることを確認します。

1
2
3
4
5
{
  "mounts": [
    "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
  ]
}

まとめ

VSCode Dev Containersは、開発環境の構築と管理を大幅に効率化するツールです。本記事で解説した内容を実践することで、以下のメリットを得られます。

  • devcontainer.jsonによる開発環境のコード化
  • Featuresによる機能の宣言的な追加
  • 言語・フレームワークに応じた最適な環境構築
  • Docker Composeとの連携による複合環境の実現
  • ライフサイクルスクリプトによる自動化
  • チーム全員での統一環境の共有

「自分の環境では動く」問題から解放され、本質的な開発作業に集中できる環境を構築してください。

参考リンク