---
title: Docker Sandbox
description: Create local persistent containers from an image or Dockerfile.
url: "https://eve.dev/docs/sandbox/docker"
docs_index: /llms.txt
---

> For an index of all documentation, see [/llms.txt](/llms.txt).

A Docker sandbox runs each session in its own local container, which keeps its files between turns. The container comes from eve's default image, an existing OCI image, or `agent/sandbox/Dockerfile`.

```ts title="agent/sandbox.ts"
import { defineSandbox } from "eve/sandbox";
import { DockerSandbox } from "eve/sandbox/docker";

export const environment = DockerSandbox.image("ghcr.io/acme/agent@sha256:...");

// networkPolicy is optional: "allow-all" or "deny-all"
export default defineSandbox(() => environment.open({ networkPolicy: "deny-all" }));
```

## Choose the base image

The three constructors create the same Docker environment. They differ only in how you pass the base image:

| Constructor                                 | Base image without a Dockerfile          |
| ------------------------------------------- | ---------------------------------------- |
| `DockerSandbox.environment({ image })`      | `image`, or eve's default image if unset |
| `DockerSandbox.image("ghcr.io/acme/agent")` | The image reference you pass             |
| `DockerSandbox.dockerfile()`                | eve's default image                      |

When `agent/sandbox/Dockerfile` exists, eve builds it during preparation with `agent/sandbox/` as the build context. The result is the base image for every constructor, and it overrides any `image` you pass, including `DockerSandbox.image(ref)`. To use an existing image, remove the Dockerfile.

Use `DockerSandbox.dockerfile()`, which takes no `image` option, to make the sandbox file show that it uses the Dockerfile.

## eve's default image

eve's default image runs Ubuntu with Node.js 24, npm, Python 3, git, ripgrep, jq, and curl. Commands run as the `vercel-sandbox` user in `/workspace`, with passwordless `sudo`. Docker pulls it from `ghcr.io/vercel/eve`, and [Vercel Sandbox](/docs/sandbox/vercel) uses the same image from `vcr.vercel.com/vercel/eve/base`.

The default image doesn't include pnpm or pip, so install them in `prepare` when your agent needs them:

- `npm install -g pnpm` installs pnpm for the `vercel-sandbox` user.
- Ubuntu's system Python refuses `pip install`, so run `sudo apt-get install -y python3-venv` and use the pip inside a virtual environment.

For example, this sandbox installs matplotlib once for every session:

```ts title="agent/sandbox/sandbox.ts"
import { DefaultSandbox, defineSandbox } from "eve/sandbox";

export const environment = DefaultSandbox.environment({
  prepare: async (sandbox) => {
    for (const command of [
      "sudo apt-get update && sudo apt-get install -y python3-venv",
      "python3 -m venv /workspace/.venv",
      "/workspace/.venv/bin/pip install matplotlib==3.10.8",
    ]) {
      const result = await sandbox.run({ command });
      if (result.exitCode !== 0) {
        throw new Error(`Sandbox setup failed: ${result.stderr || result.stdout}`);
      }
    }
  },
});

export default defineSandbox(() => environment.open());
```

Tools then run `/workspace/.venv/bin/python` through `ctx.getSandbox()`. `sandbox.run()` returns a non-zero `exitCode` instead of throwing, so check it before using a command's output.

Preparation runs when eve builds the template, so it needs network access to the package registries.

Each eve release pins one tag of the default image, and the tag is not the eve version. Prepared templates include the image reference, so a new eve release reuses them unless it pins a different image.

To run a different published tag, set `EVE_SANDBOX_IMAGE_TAG` in both the build and runtime environments. eve applies the tag to both registries.

## Environment options

Pass `image`, `pullPolicy`, `env`, and `prepare` to the environment. During preparation, eve copies workspace and skill files into a temporary container and runs your `prepare`. It saves the result as the template image.

## Live container options

Pass `networkPolicy` to `open()` to set the live container's policy: `"allow-all"` or `"deny-all"`.

Each session's container keeps `/workspace` in its filesystem, and a stopped container restarts with those files. `sandbox.delete()` removes the container and succeeds when it's already gone.

See the [sandbox overview](/docs/sandbox) for managed workspace, skills, parent inheritance, and custom providers.

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)