feat: dockerCompose() sandbox provider (#471)#580
Open
OdinIversen wants to merge 1 commit into
Open
Conversation
Adds a `dockerCompose()` provider that delegates container configuration to a user-managed `docker-compose.yml`. Sandcastle invokes `docker compose run -d` against a service (default `agent`) and injects only the per-run worktree bind mount, workdir, and env vars — image, networks, GPU reservations, resource limits, and dependent services live in the compose file. Closes the long-running ask in mattpocock#471: every Docker option (networks, GPUs, ulimits, depends_on, healthchecks) is now reachable via the compose file, without sandcastle having to add a flag for each. Notes for review: - `--deps` (mentioned in the issue body) is not passed: in compose v2 dependent services run by default, only `--no-deps` opts out. - `serviceName` option is included so users can target a non-default service; the issue listed this as a "natural follow-up", but shipping it now keeps the API symmetric with the existing `docker()` provider and avoids a follow-up release. - `projectName` is exposed as the lower-level primitive that the issue's follow-up `isolateDeps: true` would build on; per-session isolation itself is left as a future story. - UID pre-flight is intentionally skipped — compose users own UID via build args. - Compose file path is verified at construction time so misconfiguration fails fast, before a worktree is created. Validated end-to-end: real container started against a compose file with `devices: [{ driver: nvidia, count: all, capabilities: [gpu] }]`, `nvidia-smi -L` listed the host GPU inside the container, workdir and cleanup behaved as expected. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Someone is attempting to deploy a commit to the Matt Pocock's projects Team on Vercel. A member of the Team first needs to authorize it. |
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.
Closes #471.
Adds a
dockerCompose()sandbox provider that delegates containerconfiguration to a user-managed
docker-compose.yml. Sandcastle invokesdocker compose run -dagainst a service (defaultagent) and injectsonly the per-run worktree bind mount, workdir, and env vars. Image,
networks, GPU reservations, resource limits, and dependent services live
in the compose file — meaning every Docker option is reachable today
without sandcastle adding a flag for each.
Notes for review
--depsnot passed. The issue body suggesteddocker compose run --deps …; in compose v2 dependent services run by default and only--no-depsopts out, so the flag is omitted.serviceNameshipped. The issue listed an explicit service-name option as a "natural follow-up". Including it now keeps the API symmetric withdocker()and avoids a follow-up release; happy to drop if you'd rather defer.projectNameshipped as the lower-level primitive. The issue'sisolateDeps: truefollow-up can be built on top of this. Per-session isolation itself is left for that follow-up.Tests
src/DockerComposeLifecycle.test.ts(13 tests) covers the docker-compose CLI shape: argv layout,-vmounts (incl. Windows drive-letter colons),:rosuffix,-f/-p/--project-directory/--workdir/-eflags, no--user, pre-existing-container guard, best-effort cleanup.src/sandboxes/docker-compose.test.ts(18 tests) coversdockerCompose(): provider tag/name, mount validation, compose-file existence check, worktree volume, default workdir,serviceNameoverride,projectName/projectDirectory/composeFilepropagation,copyFileIn/copyFileOut.npm run typecheckandnpm run buildboth green.docker compose run -dstarted a real container,nvidia-smi -Lfromhandle.exec()listed the host GPU inside the container, workdir andclose()cleanup behaved as expected.Out of scope (per issue)
sandcastle initscaffolding for a starter compose filedockerCompose({ isolateDeps: true })per-session project isolationChangeset attached.