Dock Stay
ツールを宣言的に追加する - features の使い方・オプション・サンプル

ツールを宣言的に追加する - features

features は devcontainer.json から追加のツール(Node、Python、AWS CLI、Docker-in-Docker など)を宣言的に入れる仕組み。OCI アーティファクトとして配布され、Dockerfile を書かずに環境を拡張できる。

概念図

features diagram

構文

bash
"features": { "ghcr.io/devcontainers/features/<name>:<version>": { ...options } }

実例

公式 feature を 4 つ重ねる例。ベースは汎用 Ubuntu。

bash
{
  "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、という住み分けが一般的です。

関連トピック