ツールを宣言的に追加する - features
features は devcontainer.json から追加のツール(Node、Python、AWS CLI、Docker-in-Docker など)を宣言的に入れる仕組み。OCI アーティファクトとして配布され、Dockerfile を書かずに環境を拡張できる。
概念図
構文
"features": { "ghcr.io/devcontainers/features/<name>:<version>": { ...options } }実例
公式 feature を 4 つ重ねる例。ベースは汎用 Ubuntu。
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-22.04",
"features": {
"ghcr.io/devcontainers/features/node:1": { "version": "20" },
"ghcr.io/devcontainers/features/python:1": { "version": "3.12" },
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
}
}features とは何か
features は「既存の Dev Container イメージに、追加の install スクリプトを差し込む」仕組みです。
devcontainer.json に feature の ID とバージョンを書くと、コンテナビルド時にそのスクリプトが順に実行され、指定したツール一式がインストールされます。
配布は OCI レジストリ(主に GHCR)経由で、イメージと同じように ghcr.io/devcontainers/features/<name>:<version> の形で参照します。
公式セット(devcontainers/features リポジトリ)と、サードパーティ製のコミュニティ features が両方流通しています。
Dockerfile を書くのと何が違うか
Dockerfile でもツールは入れられますが、features を使うと次の利点があります。
- 宣言的: 「Python 3.12 を入れる」を YAML/JSON 1 行で書ける。
apt-get installやバージョン固定の泥臭さを feature に委ねられる - 再利用: 「Docker-in-Docker を使いたい」は毎回同じ作業。自前で書かずに公式をそのまま拾える
- 組み合わせ可能: 順序や依存関係は feature のメタデータで表現され、重ねるだけで安全に共存できる
- メンテが分離: Node や Python の新版が出たら feature 側が追随する。リポジトリ側のメンテが軽くなる
一方で、「OS パッケージを複雑に組み合わせる」「自社専用の初期化」などはやはり Dockerfile の方が表現力が高いので、features と Dockerfile を併用するのが現実的な構成です。
代表的な公式 features
| ID | 何を入れるか |
|---|---|
devcontainers/features/common-utils |
curl / git / zsh / ユーザー作成などの下回り |
devcontainers/features/node |
Node.js + npm(nvm ベース) |
devcontainers/features/python |
Python + pip(バージョン指定可) |
devcontainers/features/go / rust / java |
各言語ランタイム |
devcontainers/features/docker-in-docker |
コンテナ内からさらに Docker を動かす |
devcontainers/features/docker-outside-of-docker |
ホストの Docker ソケットをコンテナに渡す方式 |
devcontainers/features/aws-cli / azure-cli / gh |
クラウド・GitHub CLI |
devcontainers/features/kubectl-helm-minikube |
Kubernetes 系ツール群 |
各 feature の README に受け付けるオプション(バージョン、プラグイン、ユーザー名など)が書かれているので、まずそこを見るのが定石です。
Docker-in-Docker か Docker-outside か
開発コンテナからさらに Docker コマンドを使いたい(自前のイメージをビルド、docker compose を動かす)場合、選択肢は 2 つあります。
| 方式 | 仕組み | 利点 | 注意点 |
|---|---|---|---|
| Docker-in-Docker(DinD) | コンテナ内に独立した Docker デーモンを起動 | ホストと干渉しない/CI 環境に近い | 特権コンテナ(--privileged)が必要でリソース消費が増える |
| Docker-outside-of-Docker | ホストの /var/run/docker.sock をマウント |
軽量で既存のホスト側イメージを共有できる | ホスト側 Docker を直接操作できる(≒権限が強すぎる)、ポートや bind mount のパス解釈に癖がある |
安全性を優先する・他の開発者と独立した状態がほしいなら DinD、軽さと速さ優先なら outside、という住み分けが一般的です。
関連トピック
devcontainer.json- `devcontainer.json` は Dev Container の設定を記述する中心ファイル。ベースイメージ、ポート転送、VS Code 拡張、起動後コマンドなどをまとめて指定する。 devcontainer- Dev Containers は、開発環境そのものをコンテナとして記述・配布する仕組み。VS Code Dev Containers 拡張や GitHub Codespaces と組み合わせ、「誰の手元でも同じ環境」を即座に立ち上げられる。 dockerComposeFile- Dev Container は単一コンテナだけでなく、`docker-compose.yml` と組み合わせて DB や Redis などを含む複数サービス構成にできる。アプリ側のコンテナを `service` として指定する。 