sandboxes: rewrite for microvm-based sandboxes

Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
David Karlsson
2026-01-13 11:22:26 +01:00
parent 993a94bab5
commit 2869118ccb
13 changed files with 1320 additions and 494 deletions

View File

@@ -1,6 +1,7 @@
(?i)[A-Z]{2,}'?s
jq
ripgrep
exfiltration
sandboxing
Adreno
Aleksandrov
@@ -242,6 +243,7 @@ Zsh
[Cc]ompose
[Cc]onfigs
[dD]eduplicate
[Dd]enylist
[Dd]ev
[Dd]iscoverability
[Dd]istroless

View File

@@ -12,59 +12,83 @@ params:
{{< summary-bar feature_name="Docker Sandboxes" >}}
Docker Sandboxes simplifies running AI agents securely on your local machine.
Designed for developers building with coding agents like Claude Code, Sandboxes
isolate your agents from your local machine while preserving a familiar
development experience. With Docker Sandboxes, agents can execute commands,
install packages, and modify files inside a containerized workspace that
mirrors your local directory. This gives you full agent autonomy without
compromising safety.
Docker Sandboxes lets you run AI coding agents in isolated environments on your
machine. If you're building with agents like Claude Code, Sandboxes provides a
secure way to give agents autonomy without compromising your system.
## Why use Docker Sandboxes
AI agents need to execute commands, install packages, and test code. Running
them directly on your host machine means they have full access to your files,
processes, and network. Docker Sandboxes isolates agents in microVMs, each with
its own Docker daemon. Agents can spin up test containers and modify their
environment without affecting your host.
You get:
- Agent autonomy without host system risk
- Private Docker daemon for running test containers
- File sharing between host and sandbox
- Network access control
For a comparison between Docker Sandboxes and other approaches to isolating
coding agents, see [Comparison to alternatives](./architecture.md#comparison-to-alternatives).
## How to use sandboxes
To create and run a sandbox:
```console
$ docker sandbox run claude ~/my-project
```
This command creates a sandbox for your workspace (`~/my-project`) and starts
the Claude Code agent inside it. The agent can now work with your code, install
tools, and run containers inside the isolated sandbox.
## How it works
When you run `docker sandbox run <agent>`:
Sandboxes run in lightweight microVMs with private Docker daemons. Each sandbox
is completely isolated - the agent runs inside the VM and can't access your
host Docker daemon, containers, or files outside the workspace.
1. Docker creates a container from a template image and mounts your current
working directory into the container at the same path.
Your workspace directory syncs between host and sandbox at the same absolute
path, so file paths in error messages match between environments.
2. Docker discovers your Git `user.name` and `user.email` configuration and
injects it into the container so commits made by the agent are attributed
to you.
Sandboxes don't appear in `docker ps` on your host because they're VMs, not
containers. Use `docker sandbox ls` to see them.
3. On first run, you're prompted to authenticate. Credentials are stored in a
Docker volume and reused for future sandboxed agents.
For technical details on the architecture, isolation model, and networking, see
[Architecture](architecture.md).
4. The agent starts inside the container with bypass permissions enabled.
### Multiple sandboxes
### Workspace mounting
Create separate sandboxes for different projects:
Your workspace directory is mounted into the container at the same absolute path
(on macOS and Linux). For example, `/Users/alice/projects/myapp` on your host
is also `/Users/alice/projects/myapp` in the container. This means:
```console
$ docker sandbox run claude ~/project-a
$ docker sandbox run claude ~/project-b
```
- File paths in error messages match your host
- Scripts with hard-coded paths work as expected
- Changes to workspace files are immediately visible on both host and container
Each sandbox is completely isolated from the others. Sandboxes persist until
you remove them, so installed packages and configuration stay available for
that workspace.
### One sandbox per workspace
## Supported agents
Docker enforces one sandbox per workspace. When you run `docker sandbox run
<agent>` in the same directory, Docker reuses the existing container. This
means state (installed packages, temporary files) persists across agent sessions
in that workspace.
Docker Sandboxes works with multiple AI coding agents:
> [!NOTE]
> To change a sandbox's configuration (environment variables, mounted volumes,
> etc.), you need to remove and recreate it. See
> [Managing sandboxes](advanced-config.md#managing-sandboxes) for details.
## Release status
Docker Sandboxes is an experimental feature. Features and setup are subject to
change.
Report issues on the [Docker Desktop issue tracker](https://github.com/docker/desktop-feedback).
- **Claude Code** - Anthropic's coding agent
- **Codex** - OpenAI's Codex agent (partial support; in development)
- **Gemini** - Google's Gemini agent (partial support; in development)
- **cagent** - Docker's [cagent](/ai/cagent/) (partial support; in development)
- **Kiro** - by AWS (partial support; in development)
## Get started
Head to the [Get started guide](get-started.md) to run your first sandboxed agent.
## Troubleshooting
See [Troubleshooting](./troubleshooting) for common configuration errors, or
report issues on the [Docker Desktop issue tracker](https://github.com/docker/desktop-feedback).

View File

@@ -1,305 +0,0 @@
---
title: Advanced configurations
linkTitle: Advanced
description: Docker access, volume mounting, environment variables, custom templates, and sandbox management.
weight: 40
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
This guide covers advanced configurations for sandboxed agents running locally.
## Managing sandboxes
### Recreating sandboxes
Since Docker enforces one sandbox per workspace, the same sandbox is reused
each time you run `docker sandbox run <agent>` in a given directory. To create
a fresh sandbox, you need to remove the existing one first:
```console
$ docker sandbox ls # Find the sandbox ID
$ docker sandbox rm <sandbox-id>
$ docker sandbox run <agent> # Creates a new sandbox
```
### When to recreate sandboxes
Sandboxes remember their initial configuration and don't pick up changes from subsequent `docker sandbox run` commands. You must recreate the sandbox to modify:
- Environment variables (the `-e` flag)
- Volume mounts (the `-v` flag)
- Docker socket access (the `--mount-docker-socket` flag)
- Credentials mode (the `--credentials` flag)
### Listing and inspecting sandboxes
View all your sandboxes:
```console
$ docker sandbox ls
```
Get detailed information about a specific sandbox:
```console
$ docker sandbox inspect <sandbox-id>
```
This shows the sandbox's configuration, including environment variables, volumes, and creation time.
### Removing sandboxes
Remove a specific sandbox:
```console
$ docker sandbox rm <sandbox-id>
```
Remove all sandboxes at once:
```console
$ docker sandbox rm $(docker sandbox ls -q)
```
This is useful for cleanup when you're done with a project or want to start fresh.
## Giving agents access to Docker
Mount the Docker socket to give agents access to Docker commands inside the
container. The agent can build images, run containers, and work with Docker
Compose setups.
> [!CAUTION]
> Mounting the Docker socket grants the agent full access to your Docker daemon,
> which has root-level privileges on your system. The agent can start or stop
> any container, access volumes, and potentially escape the sandbox. Only use
> this option when you fully trust the code the agent is working with.
### Enable Docker socket access
Use the `--mount-docker-socket` flag:
```console
$ docker sandbox run --mount-docker-socket claude
```
This mounts your host's Docker socket (`/var/run/docker.sock`) into the
container, giving the agent access to Docker commands.
> [!IMPORTANT]
> The agent can see and interact with all containers on your host, not just
> those created within the sandbox.
### Example: Testing a containerized application
If your project has a Dockerfile, the agent can build and test it:
```console
$ cd ~/my-docker-app
$ docker sandbox run --mount-docker-socket claude
```
Example conversation:
```plaintext
You: "Build the Docker image and run the tests"
Claude: *runs*
docker build -t myapp:test .
docker run myapp:test npm test
```
### What agents can do with Docker socket access
With Docker access enabled, agents can:
- Start multi-container applications with Docker Compose
- Build images for multiple architectures
- Manage existing containers on your host
- Validate Dockerfiles and test build processes
## Environment variables
Pass environment variables to configure the sandbox environment with the `-e`
flag:
```console
$ docker sandbox run \
-e NODE_ENV=development \
-e DATABASE_URL=postgresql://localhost/myapp_dev \
-e DEBUG=true \
claude
```
These variables are available to all processes in the container, including the
agent and any commands it runs. Use multiple `-e` flags for multiple variables.
### Example: Development environment setup
Set up a complete development environment:
```console
$ docker sandbox run \
-e NODE_ENV=development \
-e DATABASE_URL=postgresql://localhost/myapp_dev \
-e REDIS_URL=redis://localhost:6379 \
-e LOG_LEVEL=debug \
claude
```
Example conversation:
```plaintext
You: "Run the database migrations and start the development server"
Claude: *uses DATABASE_URL and other environment variables*
npm run migrate
npm run dev
```
### Common use cases
API keys for testing:
```console
$ docker sandbox run \
-e STRIPE_TEST_KEY=sk_test_xxx \
-e SENDGRID_API_KEY=SG.xxx \
claude
```
> [!CAUTION]
> Only use test/development API keys in sandboxes, never production keys.
Loading from .env files:
Sandboxes don't automatically load `.env` files from your workspace, but you can ask Claude to use them:
```plaintext
You: "Load environment variables from .env.development and start the server"
```
Claude can use `dotenv` tools or source the file directly.
## Volume mounting
Mount additional directories or files to share data beyond your main workspace.
Use the `-v` flag with the syntax `host-path:container-path`:
```console
$ docker sandbox run -v ~/datasets:/data claude
```
This makes `~/datasets` available at `/data` inside the container. The agent
can read and write files in this location.
Read-only mounts:
Add `:ro` to prevent modifications:
```console
$ docker sandbox run -v ~/configs/app.yml:/config/app.yml:ro claude
```
Multiple mounts:
Use multiple `-v` flags to mount several locations:
```console
$ docker sandbox run \
-v ~/datasets:/data:ro \
-v ~/models:/models \
-v ~/.cache/pip:/root/.cache/pip \
claude
```
### Example: Machine learning workflow
Set up an ML environment with shared datasets, model storage, and persistent
caches:
```console
$ docker sandbox run \
-v ~/datasets:/data:ro \
-v ~/models:/models \
-v ~/.cache/pip:/root/.cache/pip \
claude
```
This provides read-only access to datasets (preventing accidental modifications),
read-write access to save trained models, and a persistent pip cache for faster
package installs across sessions.
Example conversation:
```plaintext
You: "Train a model on the MNIST dataset and save it to /models"
Claude: *runs*
python train.py --data /data/mnist --output /models/mnist_model.h5
```
### Common use cases
Shared configuration files:
```console
$ docker sandbox run -v ~/.aws:/root/.aws:ro claude
```
Build caches:
```console
$ docker sandbox run \
-v ~/.cache/go-build:/root/.cache/go-build \
-v ~/go/pkg/mod:/go/pkg/mod \
claude
```
Custom tools:
```console
$ docker sandbox run -v ~/bin:/shared-bin:ro claude
```
## Custom templates
Create custom sandbox templates to reuse configured environments. Instead of
installing tools every time you start an agent, build a Docker image with
everything pre-installed:
```dockerfile
# syntax=docker/dockerfile:1
FROM docker/sandbox-templates:claude-code
RUN <<EOF
curl -LsSf https://astral.sh/uv/install.sh | sh
. ~/.local/bin/env
uv tool install ruff@latest
EOF
ENV PATH="$PATH:~/.local/bin"
```
Build the image, and use the [`docker sandbox run --template`](/reference/cli/docker/sandbox/run#template)
flag to start a new sandbox based on the image.
```console
$ docker build -t my-dev-env .
$ docker sandbox run --template my-dev-env claude
```
### Using standard images
You can use standard Docker images as sandbox templates, but they don't include
agent binaries, shell configuration, or runtime dependencies that Docker's
sandbox templates provide. Using a standard Python image directly fails:
```console
$ docker sandbox run --template python:3-slim claude
The claude binary was not found in the sandbox; please check this is the correct sandbox for this agent.
```
To use a standard image, create a Dockerfile that installs the agent binary,
dependencies, and shell configuration on top of your base image. This approach
makes sense when you need a specific base image (for example, an exact OS
version or a specialized image with particular build tools).

View File

@@ -0,0 +1,66 @@
---
title: Supported agents
description: AI coding agents supported by Docker Sandboxes with experimental status and configuration details.
weight: 50
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
Docker Sandboxes supports multiple AI coding agents. All agents run isolated
inside microVMs with private Docker daemons.
## Supported agents
| Agent | Command | Status | Notes |
| ----------- | -------- | ------------ | -------------------------- |
| Claude Code | `claude` | Experimental | Most tested implementation |
| Codex | `codex` | Experimental | In development |
| Gemini | `gemini` | Experimental | In development |
| cagent | `cagent` | Experimental | In development |
| Kiro | `kiro` | Experimental | In development |
## Experimental status
All agents are experimental features. This means:
- Breaking changes may occur between Docker Desktop versions
- Features may be incomplete or change significantly
- Stability and performance are not production-ready
- Limited support and documentation
Use sandboxes for development and testing, not production workloads.
## Using different agents
The agent type is specified when creating a sandbox:
```console
$ docker sandbox create claude ~/my-project
$ docker sandbox create codex ~/my-project
$ docker sandbox create gemini ~/my-project
$ docker sandbox create cagent ~/my-project
$ docker sandbox create kiro ~/my-project
```
Each agent runs in its own isolated sandbox. The agent type is bound to the
sandbox when created and cannot be changed later.
## Agent-specific configuration
Different agents may require different authentication methods or configuration.
See the agent-specific documentation:
- [Claude Code configuration](claude-code.md)
## Requirements
- Docker Desktop 4.58 or later
- Platform support:
- macOS with virtualization.framework
- API keys or credentials for your chosen agent
## Next steps
- [Claude Code configuration](claude-code.md)
- [Custom templates](templates.md)
- [Using sandboxes effectively](workflows.md)

View File

@@ -0,0 +1,207 @@
---
title: Architecture
description: Technical architecture of Docker Sandboxes including microVM isolation, private Docker daemon, and workspace syncing.
weight: 60
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
This page explains how Docker Sandboxes works and the design decisions behind
it.
## Why microVMs?
AI coding agents need to build images, run containers, and use Docker Compose.
Giving an agent access to your host Docker daemon means it can see your
containers, pull images, and run workloads directly on your system. That's too
much access for autonomous code execution.
Running the agent in a container doesn't solve this. Containers share the host
kernel (or in the case of Docker Desktop, share the same virtual machine) and
can't safely isolate something that needs its own Docker daemon.
Docker-in-Docker approaches either compromise isolation (privileged mode with
host socket mounting) or create nested daemon complexity.
MicroVMs provide the isolation boundary needed. Each sandbox gets its own VM
with a private Docker daemon. The agent can build images, start containers, and
run tests without any access to your host Docker environment. When you remove
the sandbox, everything inside - images, containers, packages - is gone.
## Isolation model
### Private Docker daemon per sandbox
Each sandbox runs a complete Docker daemon inside its VM. This daemon is
isolated from your host and from other sandboxes.
```plaintext
Host system (your Docker Desktop)
├── Your containers and images
├── Sandbox VM 1
│ ├── Docker daemon (isolated)
│ ├── Agent container
│ └── Other containers (created by agent)
└── Sandbox VM 2
├── Docker daemon (isolated)
└── Agent container
```
When an agent runs `docker build` or `docker compose up`, those commands
execute inside the sandbox using the private daemon. The agent sees only
containers it creates. It cannot access your host containers, images, or
volumes.
This architecture solves a fundamental constraint: autonomous agents need full
Docker capabilities but cannot safely share your Docker daemon.
### Hypervisor-level isolation
Sandboxes use your system's native virtualization:
- macOS: virtualization.framework
This provides hypervisor-level isolation between the sandbox and your host.
Unlike containers (which share the host kernel), VMs have separate kernels and
cannot access host resources outside their defined boundaries.
### What this means for security
The VM boundary provides:
- Process isolation - Agent processes run in a separate kernel
- Filesystem isolation - Only your workspace is accessible
- Network isolation - Sandboxes cannot reach each other
- Docker isolation - No access to host daemon, containers, or images
Network filtering adds an additional control layer for HTTP/HTTPS traffic. See
[Network policies](network-policies.md) for details on that mechanism.
## Workspace syncing
### Bidirectional file sync
Your workspace syncs to the sandbox at the same absolute path:
- Host: `/Users/alice/projects/myapp`
- Sandbox: `/Users/alice/projects/myapp`
Changes sync both ways. Edit a file on your host, and the agent sees it. The
agent modifies a file, and you see the change on your host.
This is file synchronization, not volume mounting. Files are copied between
host and VM. This approach works across different filesystems and maintains
consistent paths regardless of platform differences.
### Path preservation
Preserving absolute paths means:
- File paths in error messages match between host and sandbox
- Hard-coded paths in configuration files work correctly
- Build outputs reference paths you can find on your host
The agent sees the same directory structure you see, reducing confusion when
debugging issues or reviewing changes.
## Storage and persistence
### What persists
When you create a sandbox, these persist until you remove it:
- Docker images and containers - Built or pulled by the agent
- Installed packages - System packages added with apt, yum, etc.
- Agent state - Credentials, configuration, history
- Workspace changes - Files created or modified sync back to host
### What's ephemeral
Sandboxes are lightweight but not stateless. They persist between runs but are
isolated from each other. Each sandbox maintains its own:
- Docker daemon state
- Image cache
- Package installations
When you remove a sandbox with `docker sandbox rm`, the entire VM and its
contents are deleted. Images built inside the sandbox, packages installed, and
any state not synced to your workspace are gone.
### Disk usage
Each sandbox consumes disk space for:
- VM disk image (grows as you build images and install packages)
- Docker images pulled or built inside the sandbox
- Container layers and volumes
Multiple sandboxes do not share images or layers. Each has its own isolated
Docker daemon and storage.
## Networking
### Internet access
Sandboxes have outbound internet access through your host's network connection.
Agents can install packages, pull images, and access APIs.
An HTTP/HTTPS filtering proxy runs on your host and is available at
`host.docker.internal:3128`. Agents automatically use this proxy for outbound
web requests. You can configure network policies to control which destinations
are allowed. See [Network policies](network-policies.md).
### Sandbox isolation
Sandboxes cannot communicate with each other. Each VM has its own private
network namespace. An agent in one sandbox cannot reach services or containers
in another sandbox.
Sandboxes also cannot access your host's `localhost` services. The VM boundary
prevents direct access to services running on your host machine.
## Lifecycle
### Creating and running
`docker sandbox run` initializes a VM with a workspace for a specified agent,
and starts the agent inside an existing sandbox. You can stop and restart the
agent without recreating the VM, preserving installed packages and Docker
images.
`docker sandbox create` initializes the VM with a workspace but doesn't start
the agent automatically. This separates environment setup from agent execution.
### State management
Sandboxes persist until explicitly removed. Stopping an agent doesn't delete
the VM. This means:
- Installed packages remain available
- Built images stay cached
- Environment setup persists between runs
Use `docker sandbox rm` to delete a sandbox and reclaim disk space.
## Comparison to alternatives
Understanding when to use sandboxes versus other approaches:
| Approach | Isolation | Agent Docker access | Host impact | Use case |
| --------------------------- | ----------------- | ------------------------ | ----------------------------------- | --------------------------------------------- |
| Sandboxes (microVMs) | Hypervisor-level | Private daemon | None - fully isolated | Autonomous agents building/running containers |
| Container with socket mount | Kernel namespaces | Host daemon (shared) | Agent sees all host containers | Trusted tools that need Docker CLI |
| Docker-in-Docker | Nested containers | Private daemon (complex) | Moderate - privileged mode required | CI/CD environments |
| Host execution | None | Host daemon | Full - direct system access | Manual development by trusted humans |
Sandboxes trade higher resource overhead (VM + daemon) for complete isolation.
Use containers when you need lightweight packaging without Docker access. Use
sandboxes when you need to give something autonomous full Docker capabilities
without trusting it with your host environment.
## Next steps
- [Network policies](network-policies.md)
- [Custom templates](templates.md)
- [Using sandboxes effectively](workflows.md)

View File

@@ -11,39 +11,10 @@ running Claude Code in a sandboxed environment.
## Quick start
The simplest way to start Claude in a sandbox:
To create a sandbox and run Claude Code for a project directory:
```console
$ docker sandbox run claude
```
This starts a sandboxed Claude Code agent with the current working directory as
its workspace.
Or specify a different workspace:
```console
$ docker sandbox run -w ~/my-project claude
```
## Passing CLI options to Claude
Claude Code supports various command-line options that you can pass through
`docker sandbox run`. Any arguments after the agent name (`claude`) are passed
directly to Claude Code inside the sandbox.
### Continue previous conversation
Resume your most recent conversation:
```console
$ docker sandbox run claude -c
```
Or use the long form:
```console
$ docker sandbox run claude --continue
$ docker sandbox run claude ~/my-project
```
### Pass a prompt directly
@@ -51,103 +22,94 @@ $ docker sandbox run claude --continue
Start Claude with a specific prompt:
```console
$ docker sandbox run claude "Add error handling to the login function"
$ docker sandbox run <sandbox-name> -- "Add error handling to the login function"
```
Or:
```console
$ docker sandbox run <sandbox-name> -- "$(cat prompt.txt)"
```
This starts Claude and immediately processes the prompt.
### Combine options
You can combine sandbox options with Claude options:
```console
$ docker sandbox run -e DEBUG=1 claude -c
```
This creates a sandbox with `DEBUG` set to `1`, enabling debug output for
troubleshooting, and continues the previous conversation.
### Available Claude options
All Claude Code CLI options work through `docker sandbox run`:
- `-c, --continue` - Continue the most recent conversation
- `-p, --prompt` - Read prompt from stdin (useful for piping)
- `--dangerously-skip-permissions` - Skip permission prompts (enabled by default in sandboxes)
- And more - see the [Claude Code documentation](https://docs.claude.com/en/docs/claude-code) for a complete list
## Authentication
Claude sandboxes support the following credential management strategies.
Claude Code needs an Anthropic API key to work. The recommended approach is to
set the `ANTHROPIC_API_KEY` environment variable in your shell configuration
file.
### Strategy 1: `sandbox` (Default)
Docker Sandboxes run through a daemon process that doesn't inherit environment
variables from your current shell session. To make your API key available to
sandboxes, you need to set it globally in your shell configuration file.
```console
$ docker sandbox run claude
Add the API key to your shell configuration file:
```plaintext {title="~/.bashrc or ~/.zshrc"}
export ANTHROPIC_API_KEY=sk-ant-api03-xxxxx
```
On first run, Claude prompts you to enter your Anthropic API key. The
credentials are stored in a persistent Docker volume named
`docker-claude-sandbox-data`. All future Claude sandboxes automatically use
these stored credentials, and they persist across sandbox restarts and deletion.
Then apply the changes:
Sandboxes mount this volume at `/mnt/claude-data` and create symbolic links in
the sandbox user's home directory.
> [!NOTE]
> If your workspace contains a `.claude.json` file with a `primaryApiKey`
> field, you'll receive a warning about potential conflicts. You can choose to
> remove the `primaryApiKey` field from your `.claude.json` or proceed and
> ignore the warning.
### Strategy 2: `none`
No automatic credential management.
1. Source your shell configuration: `source ~/.bashrc` (or `~/.zshrc`)
2. Restart Docker Desktop so the daemon picks up the new environment variable
3. Create and run your sandbox:
```console
$ docker sandbox run --credentials=none claude
$ docker sandbox create claude ~/project
$ docker sandbox run <sandbox-name>
```
Docker does not discover, inject, or store any credentials. You must
authenticate manually inside the container. Credentials are not shared with
other sandboxes but persist for the lifetime of the container.
The sandbox will detect the environment variable and use it automatically.
### Interactive authentication
If no credentials are found, Claude Code prompts you to authenticate when it
starts. You'll need to authenticate for each workspace separately when using
this method.
To avoid repeated authentication, use the `ANTHROPIC_API_KEY` environment
variable method described above.
## Configuration
Claude Code can be configured through CLI options. Any arguments you pass after
the agent name are passed directly to Claude Code inside the container.
the sandbox name and a `--` separator are passed directly to Claude Code.
Pass options after the agent name:
Pass options after the sandbox name:
```console
$ docker sandbox run claude [claude-options]
$ docker sandbox run <sandbox-name> -- [claude-options]
```
For example:
```console
$ docker sandbox run claude --continue
$ docker sandbox run <sandbox-name> -- --continue
```
See the [Claude Code CLI reference](https://docs.claude.com/en/docs/claude-code/cli-reference)
for a complete list of available options.
## Advanced usage
For more advanced configurations including environment variables, volume mounts,
Docker socket access, and custom templates, see
[Advanced configurations](advanced-config.md).
for available options.
## Base image
The `docker/sandbox-templates:claude-code` image includes Claude Code with
automatic credential management, plus development tools (Docker CLI, GitHub
CLI, Node.js, Go, Python 3, Git, ripgrep, jq). It runs as a non-root `agent`
user with `sudo` access and launches Claude with
`--dangerously-skip-permissions` by default.
The Claude Code sandbox template is a container image that runs inside the
sandbox VM. It includes:
## Next Steps
- Ubuntu-based environment with Claude Code
- Development tools: Docker CLI, GitHub CLI, Node.js, Go, Python 3, Git, ripgrep, jq
- Non-root `agent` user with sudo access
- Private Docker daemon for running additional containers
- [Advanced configurations](advanced-config.md)
Claude launches with `--dangerously-skip-permissions` by default in sandboxes.
You can build custom templates based on `docker/sandbox-templates:claude-code`.
See [Custom templates](templates.md) for details.
## Next steps
- [Using sandboxes effectively](workflows.md)
- [Custom templates](templates.md)
- [Network policies](network-policies.md)
- [Troubleshooting](troubleshooting.md)
- [CLI Reference](/reference/cli/docker/sandbox/)

View File

@@ -7,57 +7,70 @@ weight: 20
{{< summary-bar feature_name="Docker Sandboxes" >}}
This guide will help you run Claude Code in a sandboxed environment for the first time.
This guide runs Claude Code in an isolated sandbox for the first time.
> [!NOTE]
> Upgrading from an earlier version of Docker Desktop? See the
> [migration guide](migration.md) for information about the new microVM
> architecture.
## Prerequisites
Before you begin, ensure you have:
- Docker Desktop 4.50 or later
- A Claude Code subscription
- Docker Desktop 4.58 or later
- macOS
- A Claude API key
## Run a sandboxed agent
## Run your first sandbox
Follow these steps to run Claude Code in a sandboxed environment:
Follow these steps to run Claude Code:
1. Navigate to Your Project
1. Set your Anthropic API key as an environment variable.
```console
$ cd ~/my-project
Add the API key to your shell configuration file:
```plaintext {title="~/.bashrc or ~/.zshrc"}
export ANTHROPIC_API_KEY=sk-ant-api03-xxxxx
```
2. Start Claude in a sandbox
Docker Sandboxes use a daemon process that runs independently of your
current shell session. This means setting the environment variable inline or
in your current session will not work. You must set it globally in your
shell configuration file to ensure the daemon can access it.
Then apply the changes:
1. Source your shell configuration.
2. Restart Docker Desktop so the daemon picks up the new environment variable.
2. Create and run a sandbox for Claude Code for your workspace:
```console
$ docker sandbox run claude
$ docker sandbox run claude ~/my-project
```
3. Authenticate: on first run, Claude will prompt you to authenticate.
This creates a microVM sandbox. Docker assigns it a name automatically.
Once you've authenticated, the credentials are stored in a persistent Docker
volume and reused for future sessions.
4. Claude Code launches inside the container.
3. Claude Code starts and you can begin working. The first run takes longer
while Docker initializes the microVM and pulls the template image.
## What just happened?
When you ran `docker sandbox run claude`:
When you ran `docker sandbox run`:
- Docker created a container from a template image
- Your current directory was mounted at the same path inside the container
- Your Git name and email were injected into the container
- Your API key was stored in a Docker volume (`docker-claude-sandbox-data`)
- Claude Code started with bypass permissions enabled
- Docker created a lightweight microVM with a private Docker daemon
- The sandbox was assigned a name based on the workspace path
- Your workspace synced into the VM
- Docker started the Claude Code agent as a container inside the sandbox VM
The container continues running in the background. Running `docker sandbox run
claude` again in the same directory reuses the existing container, allowing the
agent to maintain state (installed packages, temporary files) across sessions.
The sandbox persists until you remove it. Installed packages and configuration
remain available. Run `docker sandbox run <sandbox-name>` again to reconnect.
## Basic commands
Here are a few essential commands to manage your sandboxes:
Here are essential commands to manage your sandboxes:
### List your sandboxes
### List sandboxes
```console
$ docker sandbox ls
@@ -65,30 +78,54 @@ $ docker sandbox ls
Shows all your sandboxes with their IDs, names, status, and creation time.
> [!NOTE]
> Sandboxes don't appear in `docker ps` because they're microVMs, not
> containers. Use `docker sandbox ls` to see them.
### Access a running sandbox
```console
$ docker sandbox exec -it <sandbox-name> bash
```
Executes a command inside the container in the sandbox. Use `-it` to open an
interactive shell for debugging or installing additional tools.
### Remove a sandbox
```console
$ docker sandbox rm <sandbox-id>
$ docker sandbox rm <sandbox-name>
```
Deletes a sandbox when you're done with it. Get the sandbox ID from `docker sandbox ls`.
### View sandbox details
Deletes the sandbox VM and all installed packages inside it. You can remove
multiple sandboxes at once by specifying multiple names:
```console
$ docker sandbox inspect <sandbox-id>
$ docker sandbox rm <sandbox-1> <sandbox-2>
```
Shows detailed information about a specific sandbox in JSON format.
### Recreate a sandbox
For a complete list of all commands and options, see the [CLI reference](/reference/cli/docker/sandbox/).
To start fresh with a clean environment, remove and recreate the sandbox:
## Next Steps
```console
$ docker sandbox rm <sandbox-name>
$ docker sandbox run claude ~/project
```
Now that you have Claude running in a sandboxed environment, learn more about:
Configuration like custom templates and workspace paths are set when you create
the sandbox. To change these settings, remove and recreate.
- [Authentication strategies](claude-code.md#authentication)
- [Configuration options](claude-code.md#configuration)
- [Advanced configurations](advanced-config.md)
- [Troubleshooting guide](troubleshooting.md)
For a complete list of commands and options, see the
[CLI reference](/reference/cli/docker/sandbox/).
## Next steps
Now that you have Claude running in a sandbox, learn more about:
- [Claude Code configuration](claude-code.md)
- [Supported agents](agents.md)
- [Using sandboxes effectively](workflows.md)
- [Custom templates](templates.md)
- [Network policies](network-policies.md)
- [Troubleshooting](troubleshooting.md)

View File

@@ -0,0 +1,189 @@
---
title: Migrating from legacy sandboxes
description: Migrate from container-based sandboxes to microVM-based sandboxes
weight: 100
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
Docker Desktop 4.58 introduces microVM-based sandboxes, replacing the previous
container-based implementation. This guide helps you migrate from legacy
sandboxes to the new architecture.
## What changed
Docker Sandboxes now run in lightweight microVMs instead of containers. Each
sandbox has a private Docker daemon, better isolation, and network filtering
policies.
After upgrading to Docker Desktop 4.58:
- Old sandboxes don't appear in `docker sandbox ls`
- They still exist as regular Docker containers and volumes
- You can see them with `docker ps -a` and `docker volume ls`
- Old sandboxes won't work with the new CLI commands
- Running `docker sandbox run` creates a new microVM-based sandbox
## Migration options
Choose the approach that fits your situation:
### Option 1: Start fresh (recommended)
This is the simplest approach for experimental features. You'll recreate your
sandbox with the new architecture.
1. Note any important configuration or installed packages in your old sandbox.
2. Remove the old sandbox containers:
```console
$ docker rm -f $(docker ps -q -a --filter="label=docker/sandbox=true")
```
3. Remove the credential volume:
```console
$ docker volume rm docker-claude-sandbox-data
```
4. Create a new microVM sandbox:
```console
$ docker sandbox create claude ~/project
$ docker sandbox run <sandbox-name>
```
5. Reinstall dependencies. Ask the agent to install needed tools:
```plaintext
You: "Install all the tools needed to build and test this project"
Claude: [Installs tools]
```
What you lose:
- API keys (re-authenticate on first run, or set `ANTHROPIC_API_KEY`)
- Installed packages (reinstall via the agent)
- Custom configuration (reconfigure as needed)
What you gain:
- Better isolation (microVM versus container)
- Private Docker daemon for test containers
- Network filtering policies
- Improved security
### Option 2: Migrate configuration
If you have extensive customization, preserve your setup by creating a custom
template.
1. Inspect your old sandbox to see what's installed:
```console
$ docker exec <old-sandbox-container> dpkg -l
```
2. Create a custom template with your tools:
```dockerfile
FROM docker/sandbox-templates:claude-code
USER root
# Install your tools
RUN apt-get update && apt-get install -y \
build-essential \
nodejs \
npm
# Install language-specific packages
RUN npm install -g typescript eslint
# Add any custom configuration
ENV EDITOR=vim
USER agent
```
3. Build your template:
```console
$ docker build -t my-sandbox-template:v1 .
```
4. Create a new sandbox with your template:
```console
$ docker sandbox create --template my-sandbox-template:v1 \
--load-local-template \
claude ~/project
```
5. Run the sandbox:
```console
$ docker sandbox run <sandbox-name>
```
If you want to share this template with your team, push it to a registry. See
[Custom templates](templates.md) for details.
## Cleanup old resources
After migrating, clean up legacy containers and volumes:
Remove specific sandbox:
```console
$ docker rm -f <old-sandbox-container>
$ docker volume rm docker-claude-sandbox-data
```
Remove all stopped containers and unused volumes:
```console
$ docker container prune
$ docker volume prune
```
> [!WARNING]
> `docker volume prune` removes ALL unused volumes, not just sandbox volumes.
> Make sure you don't have other important unused volumes before running this
> command.
## Understanding the differences
### Architecture
Old (container-based):
- Sandboxes were Docker containers
- Appeared in `docker ps`
- Mounted host Docker socket for container access
- Stored credentials in Docker volume
New (microVM-based):
- Sandboxes are lightweight microVMs
- Use `docker sandbox ls` to see them
- Private Docker daemon inside VM
- Credentials via `ANTHROPIC_API_KEY` environment variable or interactive auth
### CLI changes
Old command structure:
```console
$ docker sandbox run ~/project
```
New command structure:
```console
$ docker sandbox run claude ~/project
```
The agent name (`claude`, `codex`, `gemini`, `cagent`, `kiro`) is now a
required parameter when creating sandboxes, and you run the sandbox by name.

View File

@@ -0,0 +1,340 @@
---
title: Network policies
description: Configure network filtering policies to control outbound HTTP and HTTPS access from sandboxed agents.
weight: 55
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
Network policies control what external resources a sandbox can access through
an HTTP/HTTPS filtering proxy. Use policies to prevent agents from accessing
internal networks, enforce compliance requirements, or restrict internet access
to specific services.
Each sandbox has a filtering proxy that enforces policies for outbound HTTP and
HTTPS traffic. Connection to external services over other protocols, such as
raw TCP and UDP connections, are blocked. All agent communication must go
through the HTTP proxy or remain contained within the sandbox.
The proxy runs on an ephemeral port on your host, but from the agent
container's perspective it is accessible at `host.docker.internal:3128`.
### Security considerations
Use network policies as one layer of security, not the only layer. The microVM
boundary provides the primary isolation. Network policies add an additional
control for HTTP/HTTPS traffic.
The network filtering restricts which domains processes can connect to, but
doesn't inspect the traffic content. When configuring policies:
- Allowing broad domains like `github.com` permits access to any content on
that domain, including user-generated content. Agents could use these as
channels for data exfiltration.
- Domain fronting techniques may bypass filters by routing traffic through
allowed domains. This is inherent to HTTPS proxying.
Only allow domains you trust with your data. You're responsible for
understanding what your policies permit.
## How network filtering works
Each sandbox has an HTTP/HTTPS proxy running on your host. The proxy is
accessible from inside the sandbox at `host.docker.internal:3128`.
When an agent makes HTTP or HTTPS requests, the proxy:
1. Checks the policy rules against the host in the request. If the host is
blocked, the request is stopped immediately
2. Connects to the server. If the host was not explicitly allowed, checks the
server's IP address against BlockCIDR rules
For example, `localhost` is not in the default allow-list, but it's allowed by the
default "allow" policy. Because it's not explicitly allowed, the proxy then checks
the resolved IP addresses (`127.0.0.1` or `::1`) against the BlockCIDR rules.
Since `127.0.0.1/8` and `::1/128` are both blocked by default, this catches any
DNS aliases for localhost like `ip6-localhost`.
If an agent needs access to a service on localhost, include a port number in
the allow-list (e.g., `localhost:1234`).
HTTP requests to `host.docker.internal` are rewritten to `localhost`, so only
the name `localhost` will work in the allow-list.
## Monitor network activity
View what your agent is accessing and whether requests are being blocked:
```console
$ docker sandbox network log
```
Network logs help you understand agent behavior and define policies.
## Applying policies
Use `docker sandbox network proxy` to configure network policies for your
sandboxes. The sandbox must be running when you apply policy changes. Changes
take effect immediately and persist across sandbox restarts.
### Example: Block internal networks
Prevent agents from accessing your local network, Docker networks, and cloud
metadata services. It prevents accidental access to internal services while
allowing agents to install packages and access public APIs.
```console
$ docker sandbox network proxy my-sandbox \
--policy allow \
--block-cidr 10.0.0.0/8 \
--block-cidr 172.16.0.0/12 \
--block-cidr 192.168.0.0/16 \
--block-cidr 127.0.0.0/8
```
This policy:
- Allows internet access
- Blocks RFC 1918 private networks (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
- Blocks localhost (127.x.x.x)
> [!NOTE]
> These CIDR blocks are already blocked by default. The example above shows how
> to explicitly configure them if needed. The default policy blocks:
>
> - `10.0.0.0/8`
> - `127.0.0.0/8`
> - `169.254.0.0/16`
> - `172.16.0.0/12`
> - `192.168.0.0/16`
> - `::1/128`
> - `fc00::/7`
> - `fe80::/10`
### Example: Restrict to package managers only
For strict control, use a denylist policy that only allows package repositories:
```console
$ docker sandbox network proxy my-sandbox \
--policy deny \
--allow-host "*.npmjs.org" \
--allow-host "*.pypi.org" \
--allow-host "files.pythonhosted.org" \
--allow-host "*.rubygems.org" \
--allow-host github.com
```
> [!NOTE]
> This policy would block the backend of your AI coding agent (e.g., for Claude
> Code: `xyz.anthropic.com`). Make sure you also include hostnames that the
> agent requires.
The agent can install dependencies but can't access arbitrary internet
resources. This is useful for CI/CD environments or when running untrusted code.
### Example: Allow AI APIs and development tools
Combine AI service access with package managers and version control:
```console
$ docker sandbox network proxy my-sandbox \
--policy deny \
--allow-host api.anthropic.com \
--allow-host "*.npmjs.org" \
--allow-host "*.pypi.org" \
--allow-host github.com \
--allow-host "*.githubusercontent.com"
```
This allows agents to call AI APIs, install packages, and fetch code from
GitHub while blocking other internet access.
### Example: Allow specific APIs while blocking subdomains
Use port-specific rules and subdomain patterns for fine-grained control:
```console
$ docker sandbox network proxy my-sandbox \
--policy deny \
--allow-host api.example.com:443 \
--allow-host cdn.example.com \
--allow-host "*.storage.example.com:443"
```
This policy allows:
- Requests to `api.example.com` on port 443 (typically
`https://api.example.com`)
- Requests to `cdn.example.com` on any port
- Requests to any subdomain of `storage.example.com` on port 443, like
`us-west.storage.example.com:443` or `eu-central.storage.example.com:443`
Requests to `example.com` (any port), `www.example.com` (any port), or
`api.example.com:8080` would all be blocked because none match the specific
patterns.
To allow both a domain and all its subdomains, specify both patterns:
```console
$ docker sandbox network proxy my-sandbox \
--policy deny \
--allow-host example.com \
--allow-host "*.example.com"
```
## Policy modes: allowlist versus denylist
Policies have two modes that determine default behavior.
### Allowlist mode
Default: Allow all traffic, block specific destinations.
```console
$ docker sandbox network proxy my-sandbox \
--policy allow \
--block-cidr 192.0.2.0/24 \
--block-host example.com
```
Use allowlist mode when you want agents to access most resources but need to
block specific networks or domains. This is less restrictive and works well for
development environments where the agent needs broad internet access.
### Denylist mode
Default: Block all traffic, allow specific destinations.
```console
$ docker sandbox network proxy my-sandbox \
--policy deny \
--allow-host api.anthropic.com \
--allow-host "*.npmjs.org"
```
Use denylist mode when you want tight control over external access. This
requires explicitly allowing each service the agent needs, making it more
secure but also more restrictive. Good for production deployments, CI/CD
pipelines, or untrusted code.
### Domain and CIDR matching
Domain patterns support exact matches, wildcards, and port specifications:
- `example.com` matches only that exact domain (any port)
- `example.com:443` matches requests to `example.com` on port 443 (the default
HTTPS port)
- `*.example.com` matches all subdomains like `api.example.com` or
`www.example.com`
- `*.example.com:443` matches requests to any subdomain on port 443
Important pattern behaviors:
- `example.com` does NOT match subdomains. A request to `api.example.com`
won't match a rule for `example.com`.
- `*.example.com` does NOT match the root domain. A request to `example.com`
won't match a rule for `*.example.com`.
- To allow both a domain and its subdomains, specify both patterns:
`example.com` and `*.example.com`.
When multiple patterns could match a request, the most specific pattern wins:
1. Exact hostname and port: `api.example.com:443`
2. Exact hostname, any port: `api.example.com`
3. Wildcard patterns (longest match first): `*.api.example.com:443`,
`*.api.example.com`, `*.example.com:443`, `*.example.com`
4. Catch-all wildcards: `*:443`, `*`
5. Default policy (allow or deny)
This specificity lets you block broad patterns while allowing specific
exceptions. For example, you can block `example.com` and `*.example.com` but
allow `api.example.com:443`.
CIDR blocks match IP addresses after DNS resolution:
- `192.0.2.0/24` blocks all 192.0.2.x addresses
- `198.51.100.0/24` blocks all 198.51.100.x addresses
- `203.0.113.0/24` blocks all 203.0.113.x addresses
When you block or allow a domain, the proxy resolves it to IP addresses and
checks those IPs against CIDR rules. This means blocking a CIDR range affects
any domain that resolves to an IP in that range.
## Bypass mode for HTTPS tunneling
By default, the proxy acts as a man-in-the-middle for HTTPS connections,
terminating TLS and re-encrypting traffic with its own certificate authority.
This allows the proxy to enforce policies and inject authentication credentials
for certain services. The sandbox container trusts the proxy's CA certificate.
Some applications use certificate pinning or other techniques that don't work
with MITM proxies. For these cases, use bypass mode to tunnel HTTPS traffic
directly without inspection:
```console
$ docker sandbox network proxy my-sandbox \
--bypass-host api.service-with-pinning.com
```
You can also bypass traffic to specific IP ranges:
```console
$ docker sandbox network proxy my-sandbox \
--bypass-cidr 203.0.113.0/24
```
When traffic is bypassed, the proxy:
- Acts as a simple TCP tunnel without inspecting content
- Cannot inject authentication credentials into requests
- Cannot detect domain fronting or other evasion techniques
- Still enforces domain and port matching based on the initial connection
Use bypass mode only when necessary. Bypassed traffic loses the visibility and
security benefits of MITM inspection. If you bypass broad domains like
`github.com`, the proxy has no visibility into what the agent accesses on that
domain.
## Policy persistence
Network policies are stored in JSON configuration files.
### Per-sandbox configuration
When you run `docker sandbox network proxy my-sandbox`, the command updates the
configuration for that specific sandbox only. The policy is persisted to
`~/.docker/sandboxes/vm/my-sandbox/proxy-config.json`.
The default policy (used when creating new sandboxes) remains unchanged unless
you modify it directly.
### Default configuration
The default network policy for new sandboxes is stored at
`~/.sandboxd/proxy-config.json`. This file is created automatically when the
first sandbox starts, but only if it doesn't already exist.
The current default policy is `allow`, which permits all outbound connections
except to blocked CIDR ranges (private networks, localhost, and cloud metadata
services). This default will change to `deny` in a future release to provide
more restrictive defaults.
You can modify the default policy:
1. Edit `~/.sandboxd/proxy-config.json` directly
2. Or copy a sandbox policy to the default location:
```console
$ cp ~/.docker/sandboxes/vm/my-sandbox/proxy-config.json ~/.sandboxd/proxy-config.json
```
Review and customize the default policy to match your security requirements
before creating new sandboxes. Once created, the default policy file won't be
modified by upgrades, preserving your custom configuration.
## Next steps
- [Architecture](architecture.md)
- [Using sandboxes effectively](workflows.md)
- [Custom templates](templates.md)

View File

@@ -0,0 +1,161 @@
---
title: Custom templates
description: Create custom sandbox templates to standardize development environments with pre-installed tools and configurations.
weight: 45
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
Custom templates let you create reusable sandbox environments with
pre-installed tools and configuration. Instead of asking the agent to install
packages each time, build a template with everything ready.
## When to use custom templates
Use custom templates when:
- Multiple team members need the same environment
- You're creating many sandboxes with identical tooling
- Setup involves complex steps that are tedious to repeat
- You need specific versions of tools or libraries
For one-off work or simple setups, use the default template and ask the agent
to install what's needed.
## Building a template
Start from Docker's official sandbox templates:
```dockerfile
FROM docker/sandbox-templates:claude-code
USER root
# Install system packages
RUN apt-get update && apt-get install -y \
build-essential \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# Install development tools
RUN pip3 install --no-cache-dir \
pytest \
black \
pylint
USER agent
```
Official templates include the agent binary, Ubuntu base, development tools
(Git, Docker CLI, Node.js, Python, Go), and the non-root `agent` user with
sudo access.
### The USER pattern
Switch to `root` for system-level installations, then back to `agent` at the
end. The base template defaults to `USER agent`, so you need to explicitly
switch to root for package installations. Always switch back to `agent` before
the end of your Dockerfile so the agent runs with the correct permissions.
### Using templates
Build your template:
```console
$ docker build -t my-template:v1 .
```
Then choose how to use it:
Option 1: Load from local images (quick, for personal use)
```console
$ docker sandbox create --template my-template:v1 \
--load-local-template \
claude ~/project
$ docker sandbox run <sandbox-name>
```
The `--load-local-template` flag loads the image from your local Docker daemon
into the sandbox VM. This works for quick iteration and personal templates.
Option 2: Push to a registry (for sharing and persistence)
```console
$ docker tag my-template:v1 myorg/my-template:v1
$ docker push myorg/my-template:v1
$ docker sandbox create --template myorg/my-template:v1 claude ~/project
$ docker sandbox run <sandbox-name>
```
Pushing to a registry makes templates available to your team and persists them
beyond your local machine.
## Example: Node.js template
```dockerfile
FROM docker/sandbox-templates:claude-code
USER root
RUN apt-get update && apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js 20 LTS
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Install common tools
RUN npm install -g \
typescript@5.1.6 \
eslint@8.46.0 \
prettier@3.0.0
USER agent
```
Pin versions for reproducible builds.
## Using standard images
You can use standard Docker images (like `python:3.11` or `node:20`) as a
base, but they don't include agent binaries or sandbox configuration.
Using a standard image directly creates the sandbox but fails at runtime:
```console
$ docker sandbox create --template python:3-slim claude ~/project
✓ Created sandbox claude-sandbox-2026-01-16-170525 in VM claude-project
$ docker sandbox run claude-project
agent binary "claude" not found in sandbox: verify this is the correct sandbox type
```
To use a standard image, you'd need to install the agent binary, add sandbox
dependencies, configure the shell, and set up the `agent` user. Building from
`docker/sandbox-templates:claude-code` is simpler.
## Sharing with teams
Push templates to a registry and version them:
```console
$ docker build -t myorg/sandbox-templates:python-v1.0 .
$ docker push myorg/sandbox-templates:python-v1.0
```
Team members can then use the template:
```console
$ docker sandbox create --template myorg/sandbox-templates:python-v1.0 claude ~/project
```
Using version tags (`:v1.0`, `:v2.0`) instead of `:latest` ensures stability
across your team.
## Next steps
- [Using sandboxes effectively](workflows.md)
- [Architecture](architecture.md)
- [Network policies](network-policies.md)

View File

@@ -50,21 +50,7 @@ ask your administrator to [allow beta features](/enterprise/security/hardened-de
Claude can't authenticate, or you see API key errors.
The API key is likely invalid, expired, or not configured correctly. How to fix depends on your credential mode:
If using `--credentials=sandbox` (the default):
1. Remove the stored credentials:
```console
$ docker volume rm docker-claude-sandbox-data
```
2. Start a new sandbox and complete the authentication workflow:
```console
$ docker sandbox run claude
```
The API key is likely invalid, expired, or not configured correctly.
## Workspace contains API key configuration

View File

@@ -0,0 +1,157 @@
---
title: Using sandboxes effectively
linkTitle: Workflows
description: Best practices and common workflows for Docker Sandboxes including dependency management, testing, and multi-project setups.
weight: 35
---
{{< summary-bar feature_name="Docker Sandboxes" >}}
This guide covers practical patterns for working with sandboxed agents.
## Basic workflow
Create a sandbox for your project:
```console
$ cd ~/my-project
$ docker sandbox run claude .
```
The sandbox persists. Stop and restart it without losing installed packages or
configuration:
```console
$ docker sandbox run <sandbox-name> # Reconnect later
```
## Installing dependencies
Ask the agent to install what's needed:
```plaintext
You: "Install pytest and black"
Claude: [Installs packages via pip]
You: "Install build-essential"
Claude: [Installs via apt]
```
The agent has sudo access. Installed packages persist for the sandbox lifetime.
This works for system packages, language packages, and development tools.
For teams or repeated setups, use [Custom templates](templates.md) to
pre-install tools.
## Docker inside sandboxes
Agents can build images, run containers, and use Docker Compose. Everything
runs inside the sandbox's private Docker daemon.
### Testing containerized apps
```plaintext
You: "Build the Docker image and run the tests"
Claude: *runs*
docker build -t myapp:test .
docker run myapp:test npm test
```
Containers started by the agent run inside the sandbox, not on your host. They
don't appear in your host's `docker ps`.
### Multi-container stacks
```plaintext
You: "Start the application with docker-compose and run integration tests"
Claude: *runs*
docker-compose up -d
docker-compose exec api pytest tests/integration
docker-compose down
```
Remove the sandbox, and all images, containers, and volumes are deleted.
## What persists
While a sandbox exists:
- Installed packages (apt, pip, npm, etc.)
- Docker images and containers inside the sandbox
- Configuration changes
- Command history
When you remove a sandbox:
- Everything inside is deleted
- Your workspace files remain on your host (synced back)
To preserve a configured environment, create a [Custom template](templates.md).
## Named sandboxes
Use meaningful names for sandboxes you'll reuse:
```console
$ docker sandbox run --name myproject claude ~/project
```
Create multiple sandboxes for the same workspace:
```console
$ docker sandbox create --name dev claude ~/project
$ docker sandbox create --name staging claude ~/project
$ docker sandbox run dev
```
Each maintains separate packages, Docker images, and state, but share the
workspace files.
## Debugging
Access the sandbox directly with an interactive shell:
```console
$ docker sandbox exec -it <sandbox-name> bash
```
Inside the shell, you can inspect the environment, manually install packages,
or check Docker containers:
```console
agent@sandbox:~$ docker ps
agent@sandbox:~$ docker images
```
List all sandboxes:
```console
$ docker sandbox ls
```
## Managing multiple projects
Create sandboxes for different projects:
```console
$ docker sandbox create claude ~/project-a
$ docker sandbox create claude ~/project-b
$ docker sandbox create claude ~/work/client-project
```
Each sandbox is completely isolated. Switch between them by running the
appropriate sandbox name.
Remove unused sandboxes to reclaim disk space:
```console
$ docker sandbox rm <sandbox-name>
```
## Next steps
- [Custom templates](templates.md)
- [Architecture](architecture.md)
- [Network policies](network-policies.md)

View File

@@ -189,7 +189,7 @@ Docker Projects:
availability: Beta
Docker Sandboxes:
availability: Experimental
requires: Docker Desktop [4.50](/manuals/desktop/release-notes.md#4500) or later
requires: Docker Desktop [4.58](/manuals/desktop/release-notes.md#4580) or later
Docker Scout exceptions:
availability: Experimental
requires: Docker Scout CLI [1.15.0](/manuals/scout/release-notes/cli.md#1150) and later