はじめに
Dev Container を使い始めたとき、こんな疑問を持ったことはありませんか?
「Dockerfile でツールをインストールできるのに、なぜ devcontainer.json の features を使うの?」
今回は、この疑問に答えながら、features と Dockerfile の使い分けについて詳しく解説します。
結論:役割が違います
簡単に言うと:
- Dockerfile = アプリケーションの実行環境を構築
- features = 開発者の作業環境を拡張
この違いを理解すると、適切な使い分けができるようになります。
features とは何か?
features は、Dev Container の開発環境に機能を追加するための仕組みです。
{
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/azure-cli:1": {},
"ghcr.io/devcontainers/features/node:1": {
"version": "18"
}
}
}
このように書くだけで、GitHub CLI、Azure CLI、Node.js が自動的にインストールされます。
なぜ features が生まれたのか?
1. 開発環境の標準化
Dockerfile だけで開発環境を構築すると、チームメンバーごとに微妙な差異が生まれがちです。
# 開発者A の Dockerfile
RUN apt-get update && apt-get install -y git vim
# 開発者B の Dockerfile
RUN apt-get update && apt-get install -y git nano curl
features を使えば、必要なツールセットを標準化できます。
2. 再利用性の向上
よく使う開発ツールの組み合わせを、プロジェクト間で簡単に共有できます。
// Python プロジェクトの定番セット
{
"features": {
"ghcr.io/devcontainers/features/python:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
"ghcr.io/devcontainers-contrib/features/pre-commit:2": {}
}
}
3. メンテナンスの簡素化
features は自動的に更新され、最新のベストプラクティスが反映されます。Dockerfile で手動管理する必要がありません。
具体的な使い分け
features を使うべき場合
1. 一般的な開発ツール
{
"features": {
// Git 関連
"ghcr.io/devcontainers/features/github-cli:1": {},
// クラウド CLI
"ghcr.io/devcontainers/features/aws-cli:1": {},
// 言語ランタイム
"ghcr.io/devcontainers/features/go:1": {},
// コンテナツール
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
}
}
2. VS Code 拡張機能との連携
{
"features": {
"ghcr.io/devcontainers/features/java:1": {
"version": "17",
"installMaven": true
}
},
"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack"
]
}
}
}
3. チーム共通の開発ツール
{
"features": {
// チーム標準のリンター・フォーマッター
"ghcr.io/devcontainers-contrib/features/prettier:1": {},
"ghcr.io/devcontainers-contrib/features/eslint:1": {},
// チーム標準の開発支援ツール
"ghcr.io/devcontainers-contrib/features/jq:1": {},
"ghcr.io/devcontainers-contrib/features/yq:1": {}
}
}
Dockerfile を使うべき場合
1. アプリケーション固有の依存関係
# 特定バージョンのライブラリが必要
FROM node:18-alpine
# アプリケーションに必要な特殊なパッケージ
RUN apk add --no-cache \
libc6-compat \
python3 \
make \
g++
# カスタムビルドツール
RUN npm install -g custom-build-tool@2.3.4
2. OS レベルの設定
# タイムゾーン設定
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
# システムユーザーの作成
RUN useradd -m -s /bin/bash appuser
# カーネルパラメータの調整
RUN echo "vm.max_map_count=262144" >> /etc/sysctl.conf
3. 複雑なセットアップ手順
# 外部リポジトリからのインストール
RUN curl -fsSL https://example.com/install.sh | bash
# 複数ステップのビルドプロセス
WORKDIR /tmp
RUN git clone https://github.com/example/tool.git && \
cd tool && \
./configure --prefix=/usr/local && \
make && \
make install
実践的な例:フルスタックアプリケーション
devcontainer.json
{
"name": "Full Stack App",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
// 開発に必要なツールは features で
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "18"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.11"
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-python.python"
]
}
},
"postCreateCommand": "npm install && pip install -r requirements.txt"
}
Dockerfile
FROM ubuntu:22.04
# アプリケーション実行に必要な環境のみ
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# アプリケーション固有の設定
ENV NODE_ENV=development
ENV PYTHONUNBUFFERED=1
WORKDIR /workspace
# アプリケーションの依存関係
COPY package.json package-lock.json ./
RUN npm ci --only=production
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 3000
features の高度な使い方
1. カスタム features の作成
組織固有のツールセットを features として定義できます。
{
"features": {
"./local-features/company-tools": {}
}
}
2. features の設定カスタマイズ
{
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts",
"nodeGypDependencies": true,
"nvmInstallPath": "/usr/local/share/nvm"
}
}
}
3. 条件付き features
{
"features": {
"ghcr.io/devcontainers/features/powershell:1": {
"version": "latest"
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/devcontainers/features/common-utils",
"ghcr.io/devcontainers/features/powershell"
]
}
ベストプラクティス
1. レイヤーの分離を意識する
アプリケーション層(Dockerfile)
├── OS設定
├── システムパッケージ
└── アプリケーション依存関係
開発ツール層(features)
├── CLI ツール
├── 言語ランタイム
└── 開発支援ツール
2. チーム間での共有を前提に設計
{
// 必須の features
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"username": "vscode",
"upgradePackages": true
}
},
// オプションの features はコメントで提供
// "ghcr.io/devcontainers/features/rust:1": {}
}
3. パフォーマンスを考慮
{
// 必要最小限の features のみインストール
"features": {
"ghcr.io/devcontainers/features/git:1": {
"version": "latest",
"ppa": false // 不要なリポジトリ追加を避ける
}
}
}
トラブルシューティング
features が動かない場合
-
互換性の確認
{ "image": "mcr.microsoft.com/devcontainers/base:ubuntu", // この base イメージは features 対応 } -
features のバージョン指定
{ "features": { "ghcr.io/devcontainers/features/node:1": { // 明示的なバージョン指定で問題を回避 "version": "18.17.0" } } } -
ログの確認
Dev Container の作成ログで features のインストール状況を確認できます。
まとめ
- features は開発環境の拡張に特化した仕組み
- Dockerfile はアプリケーションの実行環境構築に集中
- 適切に使い分けることで、保守性と再利用性が向上
Dev Container を使いこなすには、この使い分けが重要です。チームで開発環境を統一したい場合は、積極的に features を活用しましょう。