67 lines
3.5 KiB
Markdown
67 lines
3.5 KiB
Markdown
|
|
---
|
||
|
|
type: howto
|
||
|
|
title: Set Up a DevContainer Sandbox for Autonomous Claude Code
|
||
|
|
summary: How to run Claude Code in `--dangerously-skip-permissions` mode safely, by isolating it inside a Docker devcontainer instead of the host machine.
|
||
|
|
tags:
|
||
|
|
- type/howto
|
||
|
|
- domain/agent-orchestration
|
||
|
|
- tool/docker
|
||
|
|
- tool/claude-code
|
||
|
|
scope: global
|
||
|
|
last_updated: 2026-07-13
|
||
|
|
date: 2026-07-13
|
||
|
|
update_note: experience-driven
|
||
|
|
related: []
|
||
|
|
source: design-mode
|
||
|
|
---
|
||
|
|
|
||
|
|
# Set Up a DevContainer Sandbox for Autonomous Claude Code
|
||
|
|
|
||
|
|
## Opening
|
||
|
|
Reach for this when you want to let Claude Code run unsupervised with `--dangerously-skip-permissions` (fully autonomous, no per-action confirmation) but don't want it to have that power directly against your host filesystem — a Docker container gives it a disposable, reproducible environment instead.
|
||
|
|
|
||
|
|
## Prerequisites
|
||
|
|
|
||
|
|
- [ ] Docker + Docker Compose installed on the host
|
||
|
|
- [ ] A `docker-compose.yml` defining the sandbox service, running as a non-root user (root is refused by `--dangerously-skip-permissions`)
|
||
|
|
- [ ] `ANTHROPIC_API_KEY` available to export or place in a `.env` file
|
||
|
|
- [ ] Dev tooling baked into the image: git, gh, curl/wget, python3, nodejs (for the Claude Code runtime), ripgrep, jq at minimum
|
||
|
|
|
||
|
|
## Steps
|
||
|
|
|
||
|
|
### Step 1: Build and start the sandbox
|
||
|
|
```bash
|
||
|
|
docker compose up -d --build
|
||
|
|
```
|
||
|
|
Builds the image (if changed) and starts the container in the background.
|
||
|
|
|
||
|
|
### Step 2: Export your API key before first use
|
||
|
|
```bash
|
||
|
|
export ANTHROPIC_API_KEY=sk-ant-...
|
||
|
|
docker compose up -d --build
|
||
|
|
```
|
||
|
|
Or place `ANTHROPIC_API_KEY=sk-ant-...` in a `.env` file next to the compose file — either works, but the key must be present before the container starts if Claude Code will authenticate via env var.
|
||
|
|
|
||
|
|
### Step 3: Enter the sandbox and run Claude Code unsupervised
|
||
|
|
```bash
|
||
|
|
docker exec -it <container-name> bash
|
||
|
|
claude --dangerously-skip-permissions
|
||
|
|
```
|
||
|
|
Runs as the container's non-root user. Because the blast radius is the container's filesystem, not the host's, autonomous mode is safe to use here in a way it would not be run directly on the host.
|
||
|
|
|
||
|
|
### Step 4: Stop or reset when done
|
||
|
|
```bash
|
||
|
|
docker compose down # stop, keep persisted home volume
|
||
|
|
docker compose down -v # stop AND wipe the persisted home volume (full reset)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Verification
|
||
|
|
`docker exec -it <container-name> bash` drops you into a shell as the non-root user; `whoami` should not return `root`, and `claude --version` should succeed inside the container.
|
||
|
|
|
||
|
|
## Gotchas
|
||
|
|
|
||
|
|
- **`claude --dangerously-skip-permissions` refuses to run as root** — the container user must be non-root (with passwordless sudo if you need to install packages ad hoc); running the container as root will silently block autonomous mode.
|
||
|
|
- **Mounting `~/.claude/` read-write shares host state into the sandbox** — this carries over slash commands, settings, and MCP config, but also lets the container modify host `~/.claude/` files. Mount it `:ro` if you want the container's autonomy contained to the container's own filesystem only.
|
||
|
|
- **`network_mode: host` skips Docker's port mapping** — services in the container bind directly to host ports; if you instead use bridge networking you must add explicit port mappings or exposed ports won't be reachable.
|
||
|
|
- **A named volume for the home directory persists Claude Code auth and shell state across container restarts** — `docker compose down` alone preserves it; only `-v` wipes it. Use the volume when you want to avoid re-authenticating every session, and `-v` deliberately when you want a truly clean environment.
|