SandboxNew

Docker Sessions

Create, stream, persist, and clean up Docker sandbox sessions.

Create a DockerSandbox, start a session, run commands, then destroy the session when the workflow is done.

import { DockerSandbox } from "@anvia/sandbox";

const sandbox = new DockerSandbox({
  image: "node:22-bookworm",
  workspace: {
    mode: "ephemeral",
  },
  lifecycle: {
    ttlMs: 10 * 60_000,
    idleTimeoutMs: 60_000,
  },
  limits: {
    timeoutMs: 30_000,
    maxOutputBytes: 64_000,
    maxFileBytes: 5_000_000,
    memoryMb: 512,
    cpus: 1,
  },
  network: {
    mode: "none",
  },
});

const session = await sandbox.createSession({
  manifest: {
    files: {
      "index.js": "console.log('hello sandbox')",
    },
  },
});

try {
  const result = await session.exec({
    command: "node",
    args: ["index.js"],
  });

  console.log(result.stdout);
} finally {
  await session.destroy();
}

Safety Defaults

DockerSandbox disables network access by default, drops Docker capabilities, enables no-new-privileges, rejects unsafe paths, truncates large output, and enforces command timeouts.

Do not bind mount the host project into a sandbox for untrusted code. Stage the files a task needs through manifest, writeFile(...), or write_file.

Workspace Modes

The default workspace mode is ephemeral. Each session gets a new Docker volume, and destroy() removes it.

const sandbox = new DockerSandbox({
  workspace: {
    mode: "ephemeral",
  },
});

Use a persistent workspace only when continuity is intentional. Persistent workspaces reuse a named Docker volume and keep it after destroy() by default.

const sandbox = new DockerSandbox({
  workspace: {
    mode: "persistent",
    id: `user-${userId}`,
  },
});

You can also choose persistence per session:

const session = await sandbox.createSession({
  workspace: {
    mode: "persistent",
    id: `session-${sessionId}`,
  },
});

Streaming Commands

Use execStream(...) when command output should appear while the command is still running.

for await (const event of session.execStream({
  command: "npm",
  args: ["test"],
  timeoutMs: 60_000,
})) {
  if (event.type === "stdout" || event.type === "stderr") {
    process.stdout.write(event.text);
  }

  if (event.type === "exit") {
    console.log(event.result.exitCode);
  }
}

Lifecycle Cleanup

Set lifecycle timers when a session should clean itself up even if application code forgets to call destroy().

const sandbox = new DockerSandbox({
  lifecycle: {
    ttlMs: 10 * 60_000,
    idleTimeoutMs: 60_000,
  },
});

ttlMs is a maximum lifetime. idleTimeoutMs starts after the session has no active operations.