Skip to content

Add ports option to docker() sandbox provider#519

Open
OthmanAdi wants to merge 3 commits intomattpocock:mainfrom
OthmanAdi:implement/docker-ports-option
Open

Add ports option to docker() sandbox provider#519
OthmanAdi wants to merge 3 commits intomattpocock:mainfrom
OthmanAdi:implement/docker-ports-option

Conversation

@OthmanAdi
Copy link
Copy Markdown

Problem

When an agent starts a web server inside the sandbox container, the container is created without port mappings. The host cannot reach the service on any port the agent opens.

The workaround is a manual socat sidecar:

docker run -d --name port-forward -p 3000:3000 alpine/socat TCP-LISTEN:3000,fork,reuseaddr TCP:172.17.0.2:3000

This is not a viable option for end users.

Solution

Add a ports option to the docker() sandbox provider. Each declared port is mapped as -p <port>:<port> in the docker run command, making the port reachable from the host.

import { docker } from "@ai-hero/sandcastle/sandboxes/docker";

await run({
  agent: claudeCode("claude-opus-4-7"),
  sandbox: docker({ ports: [3000, 5173] }),
  promptFile: ".sandcastle/prompt.md",
});

Changes

File Change
src/DockerLifecycle.ts Add ports?: readonly number[] to StartContainerOptions, generate -p <port>:<port> flags
src/sandboxes/docker.ts Add ports?: readonly number[] to DockerOptions, pass through to startContainer
src/DockerLifecycle.test.ts 3 tests: single port, multiple ports, omitted
src/sandboxes/docker.test.ts 2 acceptance tests
.changeset/docker-ports-option.md Patch changeset

Test plan

  • npm test -- src/DockerLifecycle.test.ts src/sandboxes/docker.test.ts — 26/26 pass
  • All new tests pass, no regressions in the Docker test files
  • Type check: no new errors beyond the pre-existing @daytona/sdk peer dep issue

When an agent starts a web server inside the sandbox, the container is
created without port mappings by default, making the service unreachable
from the host. The new ports option maps each declared port as -p <port>:<port>
in the docker run command.

  docker({ ports: [3000, 5173] })

Changes:
- StartContainerOptions: add ports?: readonly number[]
- startContainer(): generate portFlags and splice into docker run args
- DockerOptions: add ports?: readonly number[] with JSDoc and example
- docker(): pass ports through to startContainer
- DockerLifecycle.test.ts: 3 tests (single port, multiple ports, omitted)
- docker.test.ts: 2 acceptance tests
- .changeset/docker-ports-option.md: patch changeset
@vercel
Copy link
Copy Markdown

vercel Bot commented May 1, 2026

@OthmanAdi 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.

OthmanAdi added a commit to OthmanAdi/OthmanAdi that referenced this pull request May 1, 2026
OthmanAdi added 2 commits May 1, 2026 21:59
Upgrade ports type from number[] to (number | string)[] so callers
can declare either symmetric or asymmetric port mappings:

  docker({ ports: [3000, 8000] })          // -p 3000:3000 -p 8000:8000
  docker({ ports: ["3001:3000"] })         // -p 3001:3000
  docker({ ports: [5173, "3001:3000"] })   // mixed

Works for any language or framework — Python, Rust, Ruby, Angular,
Astro, React, Vue, TanStack, Next.js, etc.

Add 3 new tests: string entry pass-through, string array acceptance,
mixed number/string array acceptance. 29/29 passing.
Mirror the docker() ports feature for podman(). Same type:
  readonly ports?: readonly (number | string)[]

Same behavior: number → -p port:port, string → -p host:container.
Works for any language/framework running inside a Podman sandbox.

Add 7 tests: 3 acceptance, 4 integration (single port, multiple ports,
asymmetric string, omitted). Integration tests follow the same pattern
as existing network tests — will pass on Linux CI like all other
podman integration tests.

Update changeset to cover both docker() and podman().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant