Skip to content

driver: use stdlib tar for docker-container config files - #3996

Open
crazy-max wants to merge 2 commits into
docker:masterfrom
crazy-max:docker-container-stdlib-tar
Open

driver: use stdlib tar for docker-container config files#3996
crazy-max wants to merge 2 commits into
docker:masterfrom
crazy-max:docker-container-stdlib-tar

Conversation

@crazy-max

@crazy-max crazy-max commented Aug 5, 2026

Copy link
Copy Markdown
Member

closes #3982

This replaces the docker-container driver's config archive path with a focused stdlib tar implementation. The driver now builds the /etc/buildkit config archive directly from the in-memory file map before copying it into the BuildKit container.

The first commit removes the direct use of github.com/moby/go-archive for docker-container config copies and introduces a small tar writer based on archive/tar. The second commit removes the temporary directory staging step, validates archive paths before writing tar headers, writes deterministic directory and file entries.

The old path used a generic archive library and a host temporary directory for a very narrow job. We only need to copy generated BuildKit config files into a container, so staging those bytes on disk and then archiving them added complexity without buying us useful behavior. The new implementation makes the contract explicit: config keys are relative slash paths under /etc/buildkit, unsafe names are rejected before tar headers are written, and the copy path no longer depends on host filesystem staging.

Use a small tar writer for docker-container config files instead of the go-archive
archiver. The helper only handles the generated config tree and reads file
contents through os.Root.

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
Comment on lines +48 to +50
if len(files) > 0 {
dirs[configDir] = struct{}{}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configDir is the only name reaching writeConfigTar without passing configArchivePath. It's safe today only because len(files) > 0 makes it a prefix of every validated path. Would it be worth asserting it explicitly as well?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, fair point. configDir is currently derived from path.Base(confutil.DefaultBuildKitConfigDir), so it's buildkit today, but it's still the one path component added to the archive before going through the same explicit validation path. I will tighten that so the archive root is validated too, or refactor it so we don't pass an arbitrary root string around.


func writeConfigTar(tw *tar.Writer, dirs []string, entries []configTarEntry) error {
for _, dir := range dirs {
if err := tw.WriteHeader(&tar.Header{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we force a format format here? I think Go should select the appropriate one, but something to potentially be aware of.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think leaving Format unset is the right behavior here. The stdlib writer will pick the first format that can encode the header, which keeps simple paths as simple tar headers and still allows longer generated registry paths if needed. Forcing USTAR would make some valid config paths fail, and forcing PAX would add extended headers even when they are not needed.

Comment thread driver/docker-container/tar_test.go Outdated
require.Nil(t, rc)
}

func readTarEntries(t *testing.T, r io.Reader) map[string]tarEntry {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess here the entries are unordered, but does order matter? (e.g. ensure parent is written before child?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order shouldn't matter for Docker extraction in practice, but the implementation does write all directory entries before file entries, and both sets are sorted for deterministic output. The current test reads into a map, so it doesn't prove that ordering. I will add an explicit assertion for the tar entry sequence so this behavior is covered.

Create the docker-container BuildKit config archive directly from the in-memory
file map instead of staging files through a temporary directory.

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
@crazy-max
crazy-max force-pushed the docker-container-stdlib-tar branch from 24822b8 to d3d2609 Compare August 6, 2026 12:47

@mickael-docker mickael-docker left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants