Dev Container Featuresでdevcontainerを簡単に作る
yotaです。本ブログでたびたび話題に上がっている Visual Studio Codeのdevcontainerの機能を私も常用しています。
なかでもdevcontainerの機能の一部であるDev Container Features が、チームで必須のツールとは別に個人的に使いたいツールをdevcontainerに導入する際に便利だと感じたので紹介します。
Dev Container Featuresとは
Dev Container Features で触れられていますが、Dev Container Featuresとは既存のimageにないツールを追加してdevcontainerを作ることを簡単に実現できる機能です。
Dockerでは通常以下のような Dockerfile
を構成して所望のツールが入ったコンテナを作るアプローチを取りますが、
FROM ubuntu
# ubuntuイメージに追加のアプリケーションをinstallする
RUN apt-get install -y xxxx
Dev Container Featuresではツールのインストール処理のみを配布しておくことで、 devcontainerの設定ファイルである devcontainer.json
で組み合わせることを可能にします。
例えば、Ubuntu上にGolang(1.18)がインストールされたdevcontainerは、次のような設定で実現できます。
{
"name": "golang-on-ubuntu",
"image": "ubuntu",
"features": {
"ghcr.io/devcontainers/features/go:1.0.0": {
"version": "1.18"
}
}
}
features
フィールドで前述の「ツールのインストール処理」の配布場所を指定する形です(複数指定可能)。
他のFeatures
基本的には Dockerfile
でインストールしなければホストOS上で使っているツールはコンテナ内で使えません。
ホストOS上ではインストールしているツールをコンテナ内で使いたいが、そのためにDockerfileを書くのも手間、ということがままあったのですが、featuresによって簡単にインストールできるので重宝しています。1
例えば GitHub Flavored Markdownをローカルでプレビューしたい で紹介したGitHub CLIも導入可能です。
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
}
また、GitHub CLIやGolangのランタイムのようなツールとは違う種類のfeatureとしてdocker-outside-of-docker を使うこともあります。
これは、devcontainer上から docker
コマンドによるホストOS上のコンテナの操作を可能にします。
試してみましょう。
ホストOS
$ touch /tmp/is_hostos
$ docker run -d alpine tail -f /dev/null
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
31e352740f53: Pull complete
Digest: sha256:82d1e9d7ed48a7523bdebc18cf6290bdb97b82302a8a9c27d4fe885949ea94d1
Status: Downloaded newer image for alpine:latest
318bb825d53f4ddbb805e2d817c47fdae0afb43c18b71149d60c83e58dd5214c
$ docker ps
CONTAINER ID IMAGE
COMMAND CREATED STATUS PORTS NAMES
548ff01c1217 vsc-sample-repo-909021d9a8def8e30ae62e2b9263b878bd79b294d5e2a355c3aaa30f04e0d8ae
"/bin/sh -c 'echo Co…" 6 minutes ago Up 6 minutes admiring_hoover
318bb825d53f alpine
"tail -f /dev/null" 9 minutes ago Up 9 minutes dazzling_saha
devcontainer
root@548ff01c1217:/# cat /etc/is_hostos
cat: /etc/is_hostos: No such file or directory
root@548ff01c1217:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
548ff01c1217 vsc-sample-repo-909021d9a8def8e30ae62e2b9263b878bd79b294d5e2a355c3aaa30f04e0d8ae "/bin/sh -c 'echo Co…" 4 minutes ago Up 4 minutes admiring_hoover
318bb825d53f alpine "tail -f /dev/null" 7 minutes ago Up 7 minutes dazzling_saha
双方から docker ps
で参照できていますね。
Dev Container Featuresの仕組み
ところで、これらのfeaturesは ghcr.io/devcontainers/features/go
のように GHCR (GitHub Container Registry)上のパスを指定していますが、featuresはコンテナイメージなのでしょうか。
https://containers.dev/implementors/features/ に記載の仕様によるとそうではなく、実際はfeature自体のmetadataを表す devcontainer-feature.json
とツールのインストール処理を担う install.sh
で構成されたtgzファイルとなっています。
Reference to feature in OCI registry() () OCI registry must implement the OCI Artifact Distribution Specification.
にあるとおり、featuresで指定するレジストリはOCI Artifact Distribution Specificationに則ったレジストリです。このため、コンテナイメージ以外も格納できるので、tgzを格納して配布しています。
また、docker-outside-of-docker ではホストOS上の他のコンテナを参照できていましたが、どのようにホストOS間との連携を実現しているのでしょうか。
これはdevcontainer-feature.json
の中で追加でマウントしたいファイルを指定可能なことを活用しているようです。( docker-outside-of-dockerのdevcontainer-feature.json )
他にも仕様によればコンテナ内の環境変数やインストールするVS Codeの拡張機能も設定可能 2 になっていたりと、柔軟な処理が実現できそうです。
一方、仕様でも次のように言及されていますが、
Note: While Features may be installed on top of any base image, the implementation of a Feature might restrict it to a subset of possible base images. For example, some Features may be authored to work with a certain Linux distro (e.g. debian-based images that use the apt package manager).
install.sh
の実装によっては共に使えるimage (devcontainer.json
で指定する "image"
)が制限される場合があることには注意が必要です。
例えば install.sh
で apt install -y curl
としていた場合、 alpine linuxにはaptコマンドがないため正しく動作しません。
まとめ
devcontainerの機能として、簡単にツールのインストールのような追加の処理を実現できる機構であるfeaturesを紹介しました。
他に広く公開されているものはAvailable Dev Container Featuresに記載されており、例えばGolang以外にもいろいろな言語のランタイムやコンパイラ、kubectlなどのツールも導入可能なので便利です。
一方、追加で拡張機能のインストールや環境変数設定などのVS Codeの設定値を付与するものもあり注意が必要ですが、参考になれば幸いです。
-
devcontainerにはインストールせず、そのツールを使いたいときだけホストOS上のシェルを使うことで事足りることが多いのですが、VS Codeの機能でコンテナのボリュームに
git clone
する機能を使うとこの限りではないという事情もあります。 ↩︎ -
例えば、冒頭で例にあげたgolangのfeatureではgolangの拡張機能もインストールするように設定されます 実装(GitHub) ↩︎