Devcontainerのfeatureはビルドキャッシュされていることを知らなかった
はじめに
Devcontainer、とても便利ですね。自分は仕事、プライベートともに Devcontainer
を活用しています。そんな Devcontainer
には、事前に用意された機能を簡単に組み込むための機能としてfeaturesがあります。
自分はこの features
に関して大きな勘違いをしていました。というのは、features
で拡張した機能は毎回 Devcontainer
起動時にビルドしているという思い込みがあり、これまで積極的に活用してこなかったのでした。
今回は、せっかくなので features
がビルドキャッシュされていないという思い込みから、その思い込みが間違いと気づいたきっかけについて記録しておこうと思います。
なぜfeaturesはビルドキャ種されないという思い込みがあったのか
自分は次のように考えていました。
-
Dockerfile
で処理を明示的に記述していない -
features
は単なる機能のアドオンであり、ビルドキャッシュされることはない - だから、起動のたびに再ビルドしている
その結果、どういうことをしていたかといえば、例えば Docker Outside of Docker (dood)
の機能を利用する場合、次のような Dockerfile
と devcontainer.json
を用意しました。
FROM mcr.microsoft.com/devcontainers/javascript-node:1-22
RUN curl -fsSL https://raw.githubusercontent.com/devcontainers/features/main/src/docker-outside-of-docker/install.sh | bash
ENTRYPOINT [ "/usr/local/share/docker-init.sh" ]
CMD [ "sleep", "infinity" ]
{
"name": "Node.js",
"build": {
"dockerfile": "Dockerfile"
},
"mounts": [
{
"source": "/var/run/docker.sock",
"target": "/var/run/docker-host.sock",
"type": "bind"
}
],
"overrideCommand": false,
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
},
"customizations": {
"vscode": {
"extensions": [
"ms-azuretools.vscode-docker"
]
}
}
}
やっていることとしては、 featuresで提供されているdood機能を Dockerfile
と devcontainer
にそれぞれ記述しているだけです。
本来は devcontainer.json
で一文追加するだけで済む処理です。何かがおかしいですよね。
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
}
本当にfeaturesはビルドキャッシュされていないのか?
改めて自分の思い込みが本当かどうかを調べてみてみました。
その結果、次のような discussion
を見つけます。
上記のやり取りからすると、2023年2月1日時点では確かにビルドキャッシュされていなかったようです。ただ、その後2023年2月8日のPull Requestにて改善が入り、ビルドキャッシュが効くようになったとのことです。
素晴らしいです。
というか、自分は使い始めたのが2024年に入ってからだと思うので、おそらくすでにこの対応は含まれた状態で試しており、「featuresはビルドキャッシュしていない」は単なる思い込みであったことがわかりました。恥ずかしい...
改めて確認してみる
下記のような devcontaienr.json
を書いて、起動させてみます。Dockerfile
を書かなくてよくなり、相当シンプルになりました。
{
"name": "Node.js",
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-22",
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
}
}
下記が二度目以降の Devcontainer
の起動ログになりますが、docker-outside-of-docker
の導入処理がちゃんとキャッシュされていることがわかります。
[21277 ms] * Fetching feature: docker-outside-of-docker_0_oci
[21755 ms] * Fetched feature: docker-outside-of-docker_0_oci version 1.5.0
[21762 ms] Start: Run: docker buildx build --load --build-context dev_containers_feature_content_source=/var/folders/2r/xvl2jjqj2bv8sqtfbcqbf8480000gn/T/devcontainercli/container-features/0.65.0-1723363342921 --build-arg _DEV_CONTAINERS_BASE_IMAGE=mcr.microsoft.com/devcontainers/javascript-node:1-22 --build-arg _DEV_CONTAINERS_IMAGE_USER=root --build-arg _DEV_CONTAINERS_FEATURE_CONTENT_SOURCE=dev_container_feature_content_temp --target dev_containers_target_stage -f /var/folders/2r/xvl2jjqj2bv8sqtfbcqbf8480000gn/T/devcontainercli/container-features/0.65.0-1723363342921/Dockerfile.extended -t vsc-dood-sample-748888ecedf0dbacc0b905641a7830a853908c0c5eeb7bd2ba4a297521002780-features /Users/okhiroyuki/Library/Application Support/Code/User/globalStorage/ms-vscode-remote.remote-containers/data/empty-folder
[+] Building 4.2s (15/15) docker:rancher-desktop
=> [internal] load build definition from Dockerfile.extended 0.1s
[+] Building 4.3s (15/15) FINISHED docker:rancher-desktop
=> [internal] load build definition from Dockerfile.extended 0.1s
=> => transferring dockerfile: 2.45kB 0.0s
=> resolve image config for docker.io/docker/dockerfile:1.4 3.2s
=> CACHED docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531b 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for mcr.microsoft.com/devcontainers/javascri 0.0s
=> [context dev_containers_feature_content_source] load .dockerignore 0.1s
=> => transferring dev_containers_feature_content_source: 2B 0.0s
=> [context dev_containers_feature_content_source] load from client 0.1s
=> => transferring dev_containers_feature_content_source: 39.30kB 0.0s
=> [dev_containers_feature_content_normalize 1/3] FROM mcr.microsoft.com 0.0s
=> CACHED [dev_containers_target_stage 2/5] RUN mkdir -p /tmp/dev-contai 0.0s
=> CACHED [dev_containers_feature_content_normalize 2/3] COPY --from=dev 0.0s
=> CACHED [dev_containers_feature_content_normalize 3/3] RUN chmod -R 07 0.0s
=> CACHED [dev_containers_target_stage 3/5] COPY --from=dev_containers_f 0.0s
=> CACHED [dev_containers_target_stage 4/5] RUN echo "_CONTAINER_USER_HO 0.0s
=> CACHED [dev_containers_target_stage 5/5] RUN --mount=type=bind,from=d 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:c351526c29dce32db32738b709a1d9afeb4aed8c0901b 0.0s
=> => naming to docker.io/library/vsc-dood-sample-748888ecedf0dbacc0b905 0.0s
[27768 ms] Start: Run: docker events --format {{json .}} --filter event=start
[27773 ms] Start: Starting container
改めて、素晴らしいです。
どんどんfeaturesを活用しよう
features
がビルドキャッシュしているということがわかった今、 拡張容易性、保守性、再利用性など多くのメリットを持っているfeatures
は使わない手はなく、今後はどんどん活用していこうと考えています。
Discussion