Repository navigation
fix(compose): carry volume and tmpfs mounts onto the primary service - #143
Merged
Merged
Conversation
composeBindMounts kept only bind mounts from ResolvedConfig.Mounts, so
volume and tmpfs mounts from devcontainer.json and feature/image
metadata never reached a compose-source devcontainer. docker-in-docker
declares dind-var-lib-docker-${devcontainerId} -> /var/lib/docker as a
volume; without it the inner dockerd's data root sits on the
container's overlay root and every `docker run` fails with EINVAL
(overlay on overlay). The image path already passed every type through.
Add compose.Mount and Override.ExtraMounts and apply them on both
backends:
- native: ApplyRunOverride appends volume/tmpfs service volumes and
declares each named volume on project.Volumes so ensureNamedVolumes
creates it as <project>_<name> with the project labels;
- shell-out: WriteRunOverride emits the same service volumes and a
top-level volumes: entry for each named volume.
A target the user's compose service already mounts keeps the user's
entry; a top-level volume the user already declares is left as is.
Binds (ExtraBindMounts) are unchanged. ${devcontainerId} is already
substituted by applyMetadataMerge, as on the image path.
Cut 0.5.1 in the changelog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172W3jer4F1sxWk3US29Muz
Member
Author
|
@dap-code-review-by-crunchloop review The first review run for |
|
On it. A review of the current head is on its way. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
For compose-source devcontainers,
composeBindMountskept only bind mounts fromResolvedConfig.Mounts. Volume and tmpfs mounts fromdevcontainer.jsonand from feature/image metadata were dropped. The function's comment said other types were "silently dropped".ApplyRunOverrideandWriteRunOverridecould only add binds.docker-in-docker declares
{"source":"dind-var-lib-docker-${devcontainerId}","target":"/var/lib/docker","type":"volume"}. Without that mount, the inner dockerd's data root stays on the container's overlay root, anddocker runfails because overlay cannot be mounted on overlay. The image path (buildMounts) already passes every mount type through. This is the same class of bug as #103 (R1, "resolved but never applied"), but for mounts.Fix
This adds
compose.Mountandcompose.Override.ExtraMounts.ExtraBindMountsis unchanged. Both backends are covered (R2):ApplyRunOverrideappends volume and tmpfs service volumes. It also declares each named volume onproject.Volumes, soensureNamedVolumescreates it as<project>_<name>with the project labels.WriteRunOverrideemits the same service volumes, plus a top-levelvolumes:entry for each named volume.serializeServiceVolumenow omits an emptysourceand carriesnocopyand the tmpfssize/mode.Engine.UpfillsExtraMountsfromcfg.Mountsand from non-bindUpOptions.ExtraMounts. This is the same setbuildRunSpecuses.${devcontainerId}is already resolved byapplyMetadataMerge.ExtraMountsis rejected with an error.R3, recreate: a workspace whose features declare such a mount gets a new service-volume entry, so its config hash drifts on the first
Upafter upgrading. WithoutAdoptExisting, the primary container is recreated. That is the same drift the per-boot feature image rebuild already causes, and the container being recreated is the one that never had the mount.The CHANGELOG cuts 0.5.1. The change only adds API, which follows the v0.4.3 precedent for additive patch releases.
Tests
compose/override_mounts_test.gocovers both backends:type: volumemount produces a service volume and a project volume;readonly/nocopyand anonymous volumes;The native round trip goes through
Orchestrator.UpandserviceToRunSpec: theRunSpecgetsdc-x_dind-…, andCreateVolumereceives the project labels. The shell-out tests loaduser.ymlplus the generated override through compose-go, which is the same mergedocker composedoes.up_compose_mounts_test.gocovers the engine level:composeMounts/composeBindMountsbuilt from merged feature metadata, plusupComposeNativeandupComposeShelloutwith fakes.test/integration/compose_dind_test.gois a compose devcontainer withghcr.io/devcontainers/features/docker-in-docker:2on both backends. It checks the project volume is mounted at/var/lib/dockerand runsdocker run --rm hello-worldinside.Local results (Docker 29.1.3, Compose 2.40.3):
go test -race ./...passes on Go 1.25.14 and on 1.27.3.go vetpasses, including with-tags=integration.golangci-lintv2.5.0 reports 0 issues.mainwithout the fix, the same test fails on both backends: there is no/var/lib/dockermount, anddocker runexits 125 withfailed to mount … overlay.🤖 Generated with Claude Code
https://claude.ai/code/session_0172W3jer4F1sxWk3US29Muz