Skip to content

Instantly share code, notes, and snippets.

@AUAggy
Created February 7, 2026 05:01
Show Gist options
  • Select an option

  • Save AUAggy/129c0b4a4e86c54c0e110e3947a62fc6 to your computer and use it in GitHub Desktop.

Select an option

Save AUAggy/129c0b4a4e86c54c0e110e3947a62fc6 to your computer and use it in GitHub Desktop.
Running Claude Code in Docker Sandboxes

Running Claude Code in Docker Sandboxes

You gave an AI agent the ability to run arbitrary shell commands on your machine. Congratulations. Now you need a way to make sure it doesn't rm -rf your home directory or email your SSH keys to a stranger.

Docker Sandboxes solve this by running Claude Code inside a microVM: a lightweight virtual machine that looks like your project directory but has no access to the rest of your system. The agent gets full autonomy. Your files stay where you left them. Everybody wins.

This guide walks through setup, daily use, verification, and troubleshooting. Written for macOS; Linux users, adjust accordingly.

What You Need

  • Docker Desktop 4.58+ (the docker sandbox subcommand shipped in 4.58)
  • Claude Code CLI installed and working (claude --version)
  • An Anthropic account (API key or OAuth, your choice)

Verify everything:

docker version          # Need Docker Desktop 4.58 or later
docker ps               # Confirm the daemon is running
claude --version        # Confirm Claude Code is installed

If docker sandbox returns "not a docker command", update Docker Desktop.

How It Works (The Short Version)

When you run docker sandbox run claude ., Docker:

  1. Spins up a microVM (not a regular container; sandboxes do not appear in docker ps)
  2. Mounts your current working directory into the VM at the same absolute path
  3. Starts Claude Code with --dangerously-skip-permissions enabled by default
  4. Stores your auth credentials in a Docker volume (docker-claude-sandbox-data)

The microVM includes an Ubuntu-based environment with Node.js, Python 3, Go, Git, GitHub CLI, ripgrep, jq, and a private Docker daemon. The agent runs as a non-root agent user with sudo access.

One sandbox per workspace directory. If you run the command again in the same directory, Docker reuses the existing sandbox.

First-Time Setup

1. Create a throwaway project to test with

mkdir -p ~/claude-sandbox-test && cd ~/claude-sandbox-test
echo "# Test Project" > README.md
echo "print('Hello from the cage')" > test.py
git init && git add . && git commit -m "initial commit"

2. Launch the sandbox

docker sandbox run claude .

The first run pulls the template image and initializes the microVM, so it takes longer than subsequent runs.

3. Authenticate

Option A: API key (recommended for persistence)

Add to ~/.bashrc or ~/.zshrc:

export ANTHROPIC_API_KEY=sk-ant-api03-your-key-here

Then restart Docker Desktop. The sandbox daemon runs independently from your shell session, so it only picks up environment variables from your global shell config 1.

Option B: Interactive OAuth

On first launch, Claude Code prompts you with a URL. Open it, complete the login, return to the terminal. Credentials persist in the Docker volume until the sandbox is removed.

4. Verify isolation

Inside the sandbox, try these:

> "List all files in /Users/yourusername/"
# Expected: only the mounted project directory is visible

> "Read ~/.ssh/id_rsa"
# Expected: file not found

> "Read ~/.aws/credentials"
# Expected: file not found

If Claude can see your SSH keys, something went wrong. Stop and investigate.

5. Exit

Press Ctrl+D or type /exit.

Daily Use

Interactive session

cd ~/your-project
docker sandbox run claude .
# work, talk, iterate
# Ctrl+D when done

One-shot prompt

docker sandbox run claude . -- -p "Add input validation to the signup handler"

Reconnect to an existing sandbox

docker sandbox run my-sandbox

Background (detached) mode

docker sandbox run -d claude .
docker sandbox ls                    # check status
docker attach <sandbox-name>         # reconnect

Custom sandbox name

docker sandbox run --name api-work claude .

Sandbox Management

docker sandbox ls                              # list all sandboxes
docker sandbox stop <name>                     # stop one
docker sandbox stop $(docker sandbox ls -q)    # stop all
docker sandbox rm <name>                       # remove one
docker sandbox rm $(docker sandbox ls -aq)     # remove all
docker sandbox logs <name>                     # view logs
docker sandbox exec -it <name> bash            # drop into a shell

Sandboxes are microVMs, not containers. They will not show up in docker ps. Use docker sandbox ls.

What Gets Isolated (and What Doesn't)

Isolated:

  • Filesystem: the agent only sees your mounted workspace
  • SSH keys, AWS credentials, browser data: not mounted
  • Network: restricted (the sandbox has its own network stack)
  • Docker: the sandbox has a private Docker daemon; containers it runs stay inside

Not isolated:

  • Your project files: changes the agent makes in the workspace are reflected on your host machine immediately. This is the point. Commit before you let the agent loose.

Troubleshooting

"docker: 'sandbox' is not a docker command"

Your Docker Desktop is too old. You need 4.58 or later. Download from docker.com/products/docker-desktop.

Authentication required every time

Check the credentials volume:

docker volume ls | grep claude-sandbox-data

If missing, force a fresh auth:

docker sandbox run --credentials=none claude .

Complete the login. Credentials now persist until you destroy the sandbox or remove the volume.

Re-authenticate after session expiry

Inside an active session, type /login. Or destroy and recreate the sandbox.

Permission denied on project files

ls -la ~/your-project
sudo chown -R $(whoami) ~/your-project

Agent can't install system packages

By design. The sandbox ships with common dev tools. If you need a custom base image:

docker sandbox run --template your-custom-image:latest claude .

Multiple sandboxes eating RAM

Each sandbox uses roughly 1-2 GB of RAM. On a 16 GB machine, keep it to 2-3 simultaneous sandboxes. Monitor with docker sandbox ls and stop what you aren't using.

Git worktrees require separate auth

Known issue (docker/for-mac#7822). Each worktree path is treated as a distinct workspace, so you need to authenticate once per worktree. After that, credentials persist for each.

OAuth broken with Pro/Max plans ("proxy-managed" error)

Known issue (docker/for-mac#7842). If interactive OAuth fails, use the API key method instead.

Best Practices

  • Commit before you hand over control. The agent writes directly to your project directory. If it makes a mess, git checkout . gets you back. If you didn't commit, you get to reconstruct your changes from memory.
  • One sandbox, one project. Docker enforces this anyway (one sandbox per workspace path), but it bears repeating: don't mount broad directories.
  • Stop sandboxes when idle. They consume RAM and CPU even when sitting there doing nothing.
  • Test unfamiliar workflows in disposable directories first. Create a junk project, point the sandbox at it, see what happens.
  • Do not mount your home directory. It defeats the entire purpose of sandboxing. The agent would have access to everything you're trying to protect.

Teardown

If you want to remove everything:

docker sandbox stop $(docker sandbox ls -q)
docker sandbox rm $(docker sandbox ls -aq)
docker volume rm docker-claude-sandbox-data
docker system prune -a   # optional nuclear option for reclaiming disk space

References

  1. Docker Sandboxes for Claude Code - Official Docker documentation
  2. Getting Started with Docker Sandboxes - Prerequisites and setup
  3. docker sandbox run CLI Reference - Full command reference
  4. Docker Sandbox Workflows - Advanced usage patterns
  5. Docker Sandboxes: A New Approach for Coding Agent Safety - Design philosophy and architecture

Tested on macOS with Docker Desktop 4.59 and Claude Code CLI (Feb 2026).

Footnotes

  1. The Docker sandbox daemon runs outside your terminal session. Environment variables set with export in a running shell are invisible to it. Put them in your shell's rc file and restart Docker Desktop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment