devcontainers / devcontainers/cli

Build context for a Dev Container Feature is invalidated on every build

未关闭
#1,262 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
TypeScript
星标
3k
派生
457
平均合并
13 小时 17 分钟
30 天内合并 PR
6

描述

# Current behavior

The build context for a Dev Container Feature is invalidated on every build, even when there are no changes to the `Containerfile`, `devcontainer.json`, or any files included in the build context.

As a result, the feature installation layer is rebuilt every time instead of reusing the existing cache.

# Expected behavior

The Dev Container Feature layer should reuse the build cache whenever possible and only be rebuilt when relevant inputs have changed.

# Environment

| Component | Version |
|-----------|---------|
| OS | Ubuntu 24.04 (Kernel 6.8.0-134-generic) |
| Arch | x86_64 |
| Container runtime | Podman 4.9.3 |
| VS Code | 1.112.0 |
| Dev Container CLI | 0.87.0 |

# Steps to reproduce

```shell
cd /tmp
git clone https://github.com/devcontainers/feature-starter.git
cd feature-starter
```

Remove the `docker-in-docker` feature and add the following feature to `devcontainer.json`:

```json
"ghcr.io/devcontainers/feature-starter/color:1": {
"favorite": "green"
}
```

Build the dev container:

```shell
devcontainer build --docker-path=/usr/bin/podman
```

Build it again without making any changes:

```shell
devcontainer build --docker-path=/usr/bin/podman
```

Notice that the layer responsible for installing the feature is rebuilt instead of being restored from cache:

```text
[2/2] STEP 5/9: RUN echo "_CONTAINER_USER_HOME=$( (command -v getent >/dev/null 2>&1 && getent passwd 'root' || grep -E '^root|^[^:]*:[^:]*:root:' /etc/passwd || true) | cut -d: -f6)" >> /tmp/dev-container-features/devcontainer-features.builtin.env && echo "_REMOTE_USER_HOME=$( (command -v getent >/dev/null 2>&1 && getent passwd 'node' || grep -E '^node|^[^:]*:[^:]*:node:' /etc/passwd || true) | cut -d: -f6)" >> /tmp/dev-container-features/devcontainer-features.builtin.env
--> Using cache c466b018334665827c5d83c2c00f910ce7f80e4bff6b0eb508ac254590faffba
--> c466b0183346

[2/2] STEP 6/9: RUN --mount=type=bind,from=dev_containers_feature_content_source,source=color_0,target=/tmp/build-features-src/color_0 \
cp -ar /tmp/build-features-src/color_0 /tmp/dev-container-features \
&& chmod -R 0755 /tmp/dev-container-features/color_0 \
&& cd /tmp/dev-container-features/color_0 \
&& chmod +x ./devcontainer-features-install.sh \
&& ./devcontainer-features-install.sh \
&& rm -rf /tmp/dev-container-features/color_0

===========================================================================
Feature : My Favorite Color
Description : A feature to remind you of your favorite color
Id : ghcr.io/devcontainers/feature-starter/color
Version : 1.0.3
Options :
FAVORITE="green"
===========================================================================

Activating feature 'color'
The provided favorite color is: green
...
...
```

# Additional observations

I am not sure exactly how feature tarballs are fetched and unpacked internally, but it appears that the feature tarball is downloaded on every invocation and extracted into a versioned directory under `/tmp` whose name changes each run.

For example:

```shell
$ ls -lh /tmp/devcontainercli-foo/container-features
total 52K
drwxrwxr-x 4 mv mv 4.0K Jul 6 19:15 0.87.0-1783358140200
drwxrwxr-x 4 mv mv 4.0K Jul 6 19:16 0.87.0-1783358186697
drwxrwxr-x 4 mv mv 4.0K Jul 6 19:17 0.87.0-1783358228464
```

This changing directory name is most likely to be contributing to cache invalidation.

贡献指南

打开贡献指南

调研方向

从 feature-starter 的复现、其 devcontainer.json 以及 `devcontainer build --docker-path=/usr/bin/podman` 入口点开始。比较重复构建,并检查 `/tmp/devcontainercli-foo/container-features` 下的 feature tarball 目录;当未发生变化的构建会重用 feature 安装层,而相关输入发生变化时仍会使该层失效时,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
typescript
领域
build-system, cli
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
冷清
描述清晰度
基本清楚
新手友好度
64/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。