Devcontainer setup for claude for multiple toolchain ecosystems
Pre-built Docker images with full language toolchains for running Claude Code in isolated containers. Your code stays on your machine. The container is the sandbox. When you exit, the container is automatically destroyed.
| Image | What's Inside | Size |
|---|---|---|
claude-js |
Node 22, Bun, npm, pnpm, TypeScript, Next.js, Prisma, Vitest | ~1.2GB |
claude-rust |
Rust stable, cargo tools, mold linker, clippy, rustfmt | ~2.5GB |
claude-python |
Python 3, uv, pytest, ruff, numpy, pandas, FastAPI | ~1.0GB |
claude-go |
Go 1.24, gopls, delve, staticcheck, golangci-lint | ~1.0GB |
claude-cpp |
GCC 13, Clang, CMake, Ninja, vcpkg, Conan, Boost | ~900MB |
claude-c |
GCC 13, Clang, GDB, Valgrind, CMake, Ninja | ~600MB |
claude-ocaml |
OCaml 5.2, opam, dune, Jane Street core, async | ~1.3GB |
claude-lean |
Lean 4, elan, Lake | ~600MB |
claude-csharp |
.NET SDK 9 + 8, dotnet-ef, BenchmarkDotNet | ~1.5GB |
claude-zig |
Zig 0.13, ZLS | ~600MB |
claude-all |
Everything above in one image | ~8-10GB |
You need one of these. Both replace Docker Desktop and run the same docker commands.
Fastest option. Native macOS app, starts in ~2 seconds, minimal RAM usage. Free for personal use.
brew install orbstack
open -a OrbStackLeave it running (menu bar icon). Optional: OrbStack → Settings → "Start at login".
Free, open source, terminal-only. Slightly more setup but no GUI needed.
brew install colima docker
# Start with optimized settings for Apple Silicon
colima start \
--cpu 4 \
--memory 8 \
--disk 100 \
--vm-type vz \
--vz-rosetta \
--mount-type virtiofsAdjust --cpu and --memory based on your machine (e.g., --cpu 6 --memory 16 for Pro chips). To auto-start on login, add colima start to your shell profile or use brew services start colima.
If you have both installed (or Docker Desktop too), use contexts to switch:
# See available contexts
docker context ls
# Switch to OrbStack
docker context use orbstack
# Switch to Colima
docker context use colima
# Switch to Docker Desktop
docker context use desktop-linuxThe active context determines which runtime handles all docker commands. You only need one running at a time.
docker version
docker context ls # confirm which runtime is activegit clone https://github.com/YOUR_USERNAME/claude-containers.git ~/.claude/sandboxesOr manually:
mkdir -p ~/.claude/sandboxes
# Copy all Dockerfile.* files into ~/.claude/sandboxes/docker volume create claude-config
docker volume create build-cacheclaude-config— Saves your Claude login so you only authenticate once.build-cache— Caches downloaded packages (cargo, pip, go modules) so they aren't re-downloaded every session.
# ── Claude Containers ────────────────────────────────────
# Build a language image (run once per language)
sb-lang() {
docker build -t "claude-${1}:latest" \
-f "$HOME/.claude/sandboxes/Dockerfile.${1}" \
"$HOME/.claude/sandboxes/"
}
# Run Claude in a project
sb() {
local lang="${1:-rust}"
local project="$(cd "${2:-.}" && pwd)"
local name="claude-$(basename "$project")"
docker run -it --rm \
--name "$name" \
-v "$project":/workspace \
-v claude-config:/home/agent/.claude \
-v build-cache:/home/agent/.cache \
-w /workspace \
"claude-${lang}:latest" \
claude --dangerously-skip-permissions
}
# Open a terminal inside a running container
sb-shell() {
local project="$(cd "${1:-.}" && pwd)"
docker exec -it "claude-$(basename "$project")" bash
}
# Stop a running container
sb-down() {
local project="$(cd "${1:-.}" && pwd)"
docker stop "claude-$(basename "$project")" 2>/dev/null
}
# List running Claude containers
alias sb-ls='docker ps --filter "name=claude-" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"'
# Clean up disk space
alias sb-prune='docker system prune -f'Then reload:
source ~/.zshrcsb-lang rustTakes 5-15 minutes the first time. Cached after that — only rebuild if you edit the Dockerfile.
sb rust ~/projects/my-appOn the first run only, Claude Code prompts you to log in via browser. After that, every sb command skips login automatically.
Complete guide for running Claude Code dev containers on Windows using Podman. No Docker Desktop license needed — Podman is free and open source.
Download from podman-desktop.io. Run the installer. It handles WSL2 setup for you.
Open PowerShell as Administrator:
# Install WSL2 if not already installed
wsl --install
# Restart your computer, then:
# Install Podman
winget install RedHat.PodmanClose and reopen PowerShell after install.
winget install Microsoft.WindowsTerminalPodman on Windows runs containers inside a lightweight Linux VM. Initialize it once:
# Create the machine (uses WSL2 by default)
podman machine init
# Give it more resources (adjust to your hardware)
podman machine set --cpus 4 --memory 8192 --disk-size 100
# Start it
podman machine startVerify:
podman version
podman run quay.io/podman/helloIf the hello container prints a message, you're good.
Podman commands are nearly identical to Docker. Set up an alias so all scripts work:
# Add to your PowerShell profile
notepad $PROFILE
# Paste this line:
Set-Alias -Name docker -Value podman
# Save and close, then reload:
. $PROFILENow docker build, docker run, etc. all route through Podman.
# Clone the repo
git clone https://github.com/YOUR_USERNAME/claude-containers.git $HOME\.claude\sandboxes
# Or create manually
mkdir -p $HOME\.claude\sandboxes
# Copy all Dockerfile.* files therepodman volume create claude-config
podman volume create build-cacheOpen your PowerShell profile:
notepad $PROFILEPaste this entire block:
# ── Claude Containers (Podman) ───────────────────────────
# Build a language image (run once per language)
function sb-lang {
param([string]$Lang)
podman build -t "claude-${Lang}:latest" `
-f "$HOME\.claude\sandboxes\Dockerfile.$Lang" `
"$HOME\.claude\sandboxes\"
}
# Run Claude in a project
function sb {
param(
[string]$Lang = "rust",
[string]$Path = "."
)
$Project = (Resolve-Path $Path).Path
$Name = "claude-$(Split-Path $Project -Leaf)"
podman run -it --rm `
--name $Name `
-v "${Project}:/workspace" `
-v "claude-config:/home/agent/.claude" `
-v "build-cache:/home/agent/.cache" `
-w /workspace `
"claude-${Lang}:latest" `
claude --dangerously-skip-permissions
}
# Shell into running container
function sb-shell {
param([string]$Path = ".")
$Project = (Resolve-Path $Path).Path
$Name = "claude-$(Split-Path $Project -Leaf)"
podman exec -it $Name bash
}
# Stop a container
function sb-down {
param([string]$Path = ".")
$Project = (Resolve-Path $Path).Path
$Name = "claude-$(Split-Path $Project -Leaf)"
podman stop $Name 2>$null
}
# List running Claude containers
function sb-ls {
podman ps --filter "name=claude-" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
}
# Clean up disk space
function sb-prune {
podman system prune -f
}
# Start/stop Podman machine
function sb-start { podman machine start }
function sb-stop { podman machine stop }Save, close, reload:
. $PROFILE# Build an image (one-time per language)
sb-lang rust
sb-lang python
sb-lang js
# Start Claude in a project
cd C:\Users\YourName\projects\my-app
sb rust
# Or with explicit path
sb rust C:\Users\YourName\projects\my-app
# Or current directory (default)
sb rustFirst run will prompt browser login. After that, the claude-config volume saves your auth.
# Build
sb-lang rust # Build Rust image
sb-lang python # Build Python image
sb-lang js # Build JS/TS image
sb-lang all # Build mega image
# Run
sb rust # Current dir, Rust toolchain
sb python . # Current dir, Python
sb go C:\path\to\project # Specific path, Go
# Side terminal (new PowerShell window while Claude runs)
sb-shell # Current dir
sb-shell C:\path # Specific project
# Management
sb-ls # List running containers
sb-down # Stop current dir's container
sb-prune # Clean up disk
# Podman machine
sb-start # Start the Linux VM
sb-stop # Stop it (saves battery)# Morning: start Podman machine
sb-start
# Work on a project
cd C:\Users\YourName\projects\my-app
sb rust
# Claude launches. Work with it. Ctrl+C when done.
# Side terminal (open new PowerShell tab)
sb-shell
# Switch projects
cd C:\Users\YourName\projects\ml-thing
sb python
# End of day: stop machine (optional, saves resources)
sb-stopsb-lang lean
mkdir $HOME\practice\lean
cd $HOME\practice\lean
sb lean
# Ask Claude to teach you theorem proving
sb-lang ocaml
mkdir $HOME\practice\ocaml
cd $HOME\practice\ocaml
sb ocaml
# Ask Claude for Jane Street interview prep
sb-lang rust
mkdir $HOME\practice\rust
cd $HOME\practice\rust
sb rust
# Ask Claude to build ownership/lifetime exercisesThe Podman machine is a lightweight Linux VM that runs your containers. It needs to be running before you use any sb command.
# Check machine status
podman machine ls
# Start (do this after reboot or after sb-stop)
podman machine start
# Stop (frees RAM/CPU, run when done for the day)
podman machine stop
# Resize (if you need more resources)
podman machine stop
podman machine set --cpus 6 --memory 16384 --disk-size 150
podman machine start
# Nuclear reset (if something breaks)
podman machine rm
podman machine init
podman machine set --cpus 4 --memory 8192 --disk-size 100
podman machine start# See what's using space
podman system df
# See image sizes
podman images
# Remove an image
podman rmi claude-cpp:latest
# Remove everything unused
podman system prune -a --volumes -f| Problem | Fix |
|---|---|
| "Cannot connect to Podman" | Start the machine: podman machine start |
| "no space left on device" | podman system prune -a --volumes -f |
| Machine won't start | podman machine rm then re-init |
| Slow file I/O | Normal with WSL2 mounts. Keep projects in WSL filesystem for speed |
| "permission denied" on volume | Try: podman machine set --rootful then restart |
| Login prompt every time | Check volume: podman volume inspect claude-config |
| Podman command not found | Close and reopen PowerShell, or check PATH |
| Need Docker compatibility | Add Set-Alias -Name docker -Value podman to $PROFILE |
- Free — No license fees, even for commercial use at companies with 250+ employees
- Rootless — Containers run as your user, not as root. Better security by default
- Docker-compatible — Same commands, same Dockerfiles, same images
- No daemon — Podman doesn't run a background service eating resources
- Open source — Apache 2.0 license
All Dockerfiles work with Podman unchanged. Podman reads Dockerfiles natively (it calls them Containerfiles, but accepts both). Architecture auto-detection works the same:
- Intel/AMD →
x86_64/amd64 - ARM (Surface Pro X, Snapdragon) →
aarch64/arm64g