๐ชจ why use many token when few token do trick โ Claude Code skill that cuts 65% of tokens by talking like caveman
Docker runner for Claude Code and MCP servers
This repo packages Claude Code into a single shell script that runs it inside Docker with read-only mounts, forwarded auth, and preconfigured MCP servers. The script can pull or build the image, reuse an existing container, and start either an interactive shell or a one-shot command.
Builders who want Claude Code in an isolated Docker container with less setup.
You can run Claude Code with prebuilt tools and container isolation without setting up the image and MCP servers by hand.
What it does
Single-file runner
`run-claude.sh` includes the Dockerfile, config, and startup flow in one script.
Preconfigured MCP servers
Unsplash, Context7, and Playwright are ready to use in the container.
Auto build and pull
The script pulls a prebuilt image when possible and builds locally when needed.
Persistent container
It reuses the `claude-code` container across runs so state and changes stay available.
Read-only host mounts
SSH keys and git config are mounted read-only while the workspace stays available for edits.
Claude auth forwarding
It tries to carry your Claude login and OAuth state into the container session.
How to get it
- 1Run
# First run will automatically pull the pre-built image from Docker Hub ./run-claude.sh claude auth status # If not authenticated, you'll need to login (usually only required once) ./run-claude.sh claude /login # Test MCP servers are working ./run-claude.sh claude "search for sunset photos on unsplash"
- 2Run
# Build image only (useful for CI/CD) ./run-claude.sh --build # Force rebuild (get latest updates) ./run-claude.sh --rebuild
- 3Run
# Test Unsplash MCP ./run-claude.sh claude "find a photo of mountains using unsplash" # Test Playwright MCP ./run-claude.sh claude "take a screenshot of google.com"
- 4Run
# Use custom image name ./run-claude.sh -i my-claude:v1.0 # Build with custom name ./run-claude.sh -i my-claude:v1.0 --build
- 5Run
# Show docker command being executed RUN_CLAUDE_VERBOSE=1 ./run-claude.sh # Example output: # Running Claude Code container... # Command: docker run --rm -it --privileged --name claude-code-1234567890 ...
README
Claude Code Docker Runner
Run claude code in somewhat safe and isolated yolo mode
Features
- ๐ Standalone Script: Single file contains everything - Dockerfile, MCP servers, configuration
- ๐ค Pre-configured MCP Servers: Unsplash, Context7, and Playwright ready to use
- ๐ง Auto-build: Automatically builds Docker image if it doesn't exist
- ๐ Secure: Host system protected by Docker boundaries with read-only mounts
- โก Fast Setup: No manual Docker builds or MCP configuration needed
- ๐ Persistent Container: Reuses existing container for faster startup
Table of Contents
- Quick Start
- Script Options
- What's Included
- Testing the Setup
- Advanced Usage
- Security Notes
- Troubleshooting
- How It Works
- Contributing
- Visual Workflow
Quick Start
Prerequisites
- Docker installed and running
- Claude authentication configured (
claude auth) - Environment variables for MCP servers (e.g.,
UNSPLASH_ACCESS_KEY)
Basic Usage
# Download the script (single file needed)
curl -O https://raw.githubusercontent.com/icanhasjonas/run-claude-docker/main/run-claude.sh
chmod +x run-claude.sh
# Interactive shell (auto-pulls from Docker Hub on first run, reuses existing container)
./run-claude.sh
# Run specific command
./run-claude.sh claude --dangerously-skip-permissions "analyze this codebase"
# Custom workspace
./run-claude.sh -w /path/to/project
# If run-claude.sh fails due to architecture issues, build locally
./run-claude.sh --build
Script Options
Build Commands
# Build Docker image and exit
./run-claude.sh --build
# Force rebuild image and continue
./run-claude.sh --rebuild
Runtime Options
# Custom workspace
./run-claude.sh -w /path/to/project
# Custom Claude config path
./run-claude.sh -c /path/to/.claude
# Custom container name (default: claude-code)
./run-claude.sh -n my-claude-container
# Custom image name
./run-claude.sh -i my-claude:v1.0
# One-shot with cleanup (removes container after exit)
./run-claude.sh --rm --no-interactive claude auth status
# Safe mode (no dangerous permissions)
./run-claude.sh --safe
# Non-interactive mode
./run-claude.sh --no-interactive
# Recreate container (remove existing and create new)
./run-claude.sh --recreate
# Help
./run-claude.sh --help
Container Persistence
By default, the script creates a persistent container named claude-code that is reused across runs:
- First run: Creates and starts the container
- Subsequent runs: Reuses the existing container for faster startup
- Container running: Executes commands in the running container
- Container stopped: Restarts the existing container preserving all changes
This behavior significantly reduces startup time and preserves any modifications made inside the container (installed packages, configuration changes, etc.).
What's Included
Embedded Dockerfile
The script contains a complete Dockerfile that includes:
- Ubuntu 22.04 base image
- Claude Code installation
- Go, Node.js, Python, and build tools
- Pre-built Unsplash MCP server
- All MCP servers pre-configured
MCP Servers
Automatically configured and ready to use:
- Unsplash: Photo search and download (
unsplash-mcp-server) - Context7: AI context service (
https://mcp.context7.com/mcp) - Playwright: Browser automation (
@playwright/mcp@latest)
Environment Variables
Script Configuration
CLAUDE_CODE_IMAGE_NAME- Override default Docker Hub image (default:icanhasjonas/claude-code)
Automatically forwarded from host
UNSPLASH_ACCESS_KEYOPENAI_API_KEYNUGET_API_KEYCLAUDE_DANGEROUS_MODE=1NODE_OPTIONS=--max-old-space-size=8192TERM- Terminal settings for proper color support
Claude Authentication Forwarding
The script automatically forwards Claude authentication and OAuth credentials from your host system:
- OAuth Account: Preserves your Claude login session
- User Settings: Maintains preferences and onboarding state
- Permissions: Automatically enables bypass permissions mode in container
- Subscription: Forwards subscription and access cache information
This ensures seamless authentication without needing to re-login inside the container.
Volume Mounts
Automatically mounted:
- Workspace:
$(pwd)โ/home/$(whoami)/workspace - Claude config:
~/.claudeโ/home/$(whoami)/.claude - SSH keys:
~/.sshโ/home/$(whoami)/.ssh(read-only) - Git config:
~/.gitconfigโ/home/$(whoami)/.gitconfig(read-only)
Authentication Integration
The script makes a best effort to forward your Claude authentication into the container session:
- Seamless Login: Your existing Claude authentication is automatically available (after initial setup)
- OAuth Preservation: Maintains your logged-in state and subscription access
- Config Merging: Intelligently merges host Claude configuration with container settings
- Permission Bypass: Automatically enables bypass permissions mode for streamlined operation
Important: On your first run, you may need to run claude /login inside the container. After that initial authentication, your login state is preserved and forwarded automatically for future runs.
Testing the Setup
1. First Run (Auto-pull)
# First run will automatically pull the pre-built image from Docker Hub
./run-claude.sh claude auth status
# If not authenticated, you'll need to login (usually only required once)
./run-claude.sh claude /login
# Test MCP servers are working
./run-claude.sh claude "search for sunset photos on unsplash"
2. Test Build Commands
# Build image only (useful for CI/CD)
./run-claude.sh --build
# Force rebuild (get latest updates)
./run-claude.sh --rebuild
3. Test File Operations
# Create test project
mkdir test-project
cd test-project
echo "console.log('hello');" > test.js
# Test Claude with file modification
./run-claude.sh claude --dangerously-skip-permissions "add error handling to test.js"
# Check if file persists on host
cat test.js
4. Test MCP Integration
# Test Unsplash MCP
./run-claude.sh claude "find a photo of mountains using unsplash"
# Test Playwright MCP
./run-claude.sh claude "take a screenshot of google.com"
Advanced Usage
Custom Image Names
# Use custom image name
./run-claude.sh -i my-claude:v1.0
# Build with custom name
./run-claude.sh -i my-claude:v1.0 --build
Verbose Output
# Show docker command being executed
RUN_CLAUDE_VERBOSE=1 ./run-claude.sh
# Example output:
# Running Claude Code container...
# Command: docker run --rm -it --privileged --name claude-code-1234567890 ...
Environment Variable Setup
# Set required environment variables
export UNSPLASH_ACCESS_KEY="your-key-here"
export OPENAI_API_KEY="your-openai-key"
# Use custom Docker image
export CLAUDE_CODE_IMAGE_NAME="myregistry/my-claude-code"
./run-claude.sh
# Or use .env file approach
echo "UNSPLASH_ACCESS_KEY=your-key" >> ~/.bashrc
source ~/.bashrc
Security Notes
Container Security
- โ Host isolation: Host system protected by Docker boundaries
- โ Read-only mounts: SSH keys and system configs mounted read-only
- โ User isolation: Runs as non-root user inside container
- โ ๏ธ Privileged mode: Required for dangerous permissions functionality
Dangerous Permissions
- Container has
--privilegedflag for full system access within container - Claude runs with
--dangerously-skip-permissionsby default - Only use with trusted code and repositories
- All file modifications are contained within mounted volumes
Best Practices
- Only mount directories you want Claude to access
- Use read-only mounts for sensitive configs
- Regularly rebuild image for security updates
- Monitor container resource usage
- Use temporary containers (
--rm) for one-shot commands
Troubleshooting
Permission Issues
# Fix workspace permissions
docker run --rm -v $(pwd):/workspace claude-code:latest sudo chown -R claude:claude /workspace
Authentication Issues
First Time Setup:
On your very first run, you may need to authenticate Claude inside the container:
# Check Claude authentication status
./run-claude.sh claude auth status
# If not authenticated, login (this is usually only needed once)
./run-claude.sh claude /login
After the initial /login, the script automatically forwards your authentication between the host and container, so you shouldn't need to re-authenticate in future runs.
Note: The authentication forwarding works most of the time but isn't bulletproof. If you encounter auth issues, try running /login again inside the container.
Troubleshooting Authentication:
# Check Claude config
./run-claude.sh claude auth status
# Re-authenticate if needed
./run-claude.sh claude auth
# Or use the web login method
./run-claude.sh claude /login
Image Not Found
# Force rebuild image
./run-claude.sh --rebuild
# Or build only
./run-claude.sh --build
# Check existing images
docker images | grep claude
Container Management
# List containers
docker ps -a | grep claude
# Stop persistent container
docker stop claude-code
# Remove persistent container
docker rm claude-code
# Or use the script to recreate
./run-claude.sh --recreate
How It Works
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ HOST SYSTEM โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ./run-claude.sh โ
โ โ โ
โ โโ 1. Check if Docker image exists โ
โ โ โโ NO โ Build embedded Dockerfile โ
โ โ โโ YES โ Continue โ
โ โ โ
โ โโ 2. Check if container exists โ
โ โ โโ RUNNING โ Execute in existing container โ
โ โ โโ STOPPED โ Start existing container (preserves state) โ
โ โ โโ MISSING โ Create new container โ
โ โ โ
โ โโ 3. Mount volumes & forward env vars โ
โ โ โ
โ โผ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ DOCKER CONTAINER (Ubuntu 25.04 + Claude + MCP) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Unsplash MCP โ โ Context7 MCP โ โ Playwright MCP โ โ
โ โ (Pre-built) โ โ (HTTP/Web) โ โ (npm global) โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ CLAUDE CODE โ โ
โ โ (--dangerously-skip-permissions) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ZSH + Oh-My-Zsh + LazyVim + Dev Tools โ โ
โ โ โข Node.js (via fnm) โข Go โข Python โข Git โข Build tools โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ MOUNTED VOLUMES (Read/Write): โ
โ โข ~/.claude โ Container config โ
โ โข $(pwd) โ Working directory โ
โ โ
โ MOUNTED VOLUMES (Read-Only): โ
โ โข ~/.ssh โ SSH keys โ
โ โข ~/.gitconfig โ Git configuration โ
โ โ
โ ENV FORWARDED: โ
โ โข API Keys (Unsplash, OpenAI, etc.) โ
โ โข CLAUDE_DANGEROUS_MODE=1 โ
โ โข Claude Authentication & OAuth โ
โ โข Terminal settings (TERM) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ ISOLATION BENEFITS:
โ
Host system protected by Docker boundaries
โ
All dangerous operations contained in container
โ
Persistent containers with preserved state
โ
Pre-configured MCP servers ready to use
โ ๏ธ YOLO MODE:
โข Container runs with --privileged flag
โข Claude runs with --dangerously-skip-permissions
โข Use only with trusted projects!
The run-claude.sh script is completely self-contained:
- Embedded Dockerfile: Contains a complete Ubuntu 22.04 setup with Claude Code
- Auto-detection: Checks if Docker image exists, pulls from Docker Hub if missing, builds only with
--buildor--rebuild - Container Persistence: Reuses existing
claude-codecontainer for faster startup - MCP Setup: Automatically configures Unsplash, Context7, and Playwright servers
- Environment Forwarding: Passes through API keys, configurations, and Claude authentication
- Volume Management: Mounts workspace and config directories automatically
- User Matching: Creates container user matching your host user
No separate files needed - just the single run-claude.sh script!
Contributing
Pull requests are welcome! Feel free to contribute improvements, bug fixes, or new features.
Development Workflow
The Dockerfile is embedded directly in the run-claude.sh script to maintain the self-contained nature of the tool. When making changes to the container configuration:
-
Edit the embedded Dockerfile in the
generate_dockerfile_content()function -
Test your changes by rebuilding the container:
# Build new image and test (doesn't run container) ./run-claude.sh --build # Or rebuild and run container immediately ./run-claude.sh --rebuild -
Export for standalone use (optional):
# Export current Dockerfile for inspection or external use ./run-claude.sh --export-dockerfile Dockerfile
Key Points for Contributors
- Single source of truth: The
generate_dockerfile_content()function contains the authoritative Dockerfile - No separate Dockerfile: Everything is embedded to maintain the self-contained design
- Always test rebuilds: After changing container configuration, use
--rebuildto test - Both build options available:
--build: Just builds the image (useful for testing build process)--rebuild: Builds image and runs container (full testing)
Testing Container Changes
# After editing the embedded Dockerfile:
# Option 1: Build only (test build process)
./run-claude.sh --build
# Option 2: Rebuild and test (full workflow)
./run-claude.sh --rebuild
# Option 3: Export and inspect
./run-claude.sh --export-dockerfile debug.dockerfile
less debug.dockerfile
This workflow ensures that the container changes are properly tested while maintaining the tool's self-contained design.
Visual Workflow
flowchart TD
Start([๐ ./run-claude.sh]) --> CheckImage{๐ณ Docker Image<br/>Exists?}
CheckImage -->|No| PullImage[๐ฅ Try Pull from<br/>Docker Hub]
PullImage --> PullSuccess{Pull Success?}
PullSuccess -->|Yes| TagImage[๐ท๏ธ Tag as<br/>claude-code:latest]
PullSuccess -->|No| BuildImage[๐จ Build from<br/>Embedded Dockerfile]
TagImage --> CheckContainer
BuildImage --> CheckContainer
CheckImage -->|Yes| CheckContainer{๐ฆ Container<br/>Exists?}
CheckContainer -->|Missing| CreateContainer[โก Create New Container<br/>with Volumes & Env]
CheckContainer -->|Stopped| StartContainer[โป๏ธ Start Existing<br/>Container<br/><small>๐ฏ Preserves State</small>]
CheckContainer -->|Running| ExecContainer[๐ Execute in<br/>Running Container]
CreateContainer --> RunCommand{๐ป Command<br/>Provided?}
StartContainer --> RunCommand
ExecContainer --> RunCommand
RunCommand -->|Yes| ExecuteCmd[โก Execute:<br/>claude --dangerously-skip-permissions]
RunCommand -->|No| InteractiveShell[๐ Interactive Shell<br/>zsh + oh-my-zsh]
ExecuteCmd --> MCPServers[๐ค MCP Servers Available]
InteractiveShell --> MCPServers
MCPServers --> Unsplash[๐ธ Unsplash<br/>Photo Search]
MCPServers --> Context7[๐ง Context7<br/>AI Context]
MCPServers --> Playwright[๐ญ Playwright<br/>Browser Automation]
Unsplash --> WorkInContainer[๐ ๏ธ Work in Isolated<br/>Container Environment]
Context7 --> WorkInContainer
Playwright --> WorkInContainer
WorkInContainer --> PersistChanges[๐พ Changes Persist<br/>in Container]
PersistChanges --> End([โ
Complete])
%% Styling
classDef startEnd fill:#e1f5fe,stroke:#01579b,stroke-width:3px,color:#000
classDef decision fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#000
classDef process fill:#f3e5f5,stroke:#4a148c,stroke-width:2px,color:#000
classDef container fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px,color:#000
classDef mcp fill:#fff8e1,stroke:#f57f17,stroke-width:2px,color:#000
class Start,End startEnd
class CheckImage,PullSuccess,CheckContainer,RunCommand decision
class PullImage,TagImage,BuildImage,CreateContainer,StartContainer,ExecContainer,ExecuteCmd,InteractiveShell,WorkInContainer,PersistChanges process
class MCPServers,Unsplash,Context7,Playwright mcp
Files in the repo
- .gitignore
- CHANGELOG.md
- LICENSE
- README.md
- run-claude.sh
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More tools
The best-benchmarked open-source AI memory system. And it's free.
Orca is the ADE for working with a fleet of parallel agents. Run any coding agent with your own subscription. Available on desktop, mobile and remote runtime.

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io
Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors
Compress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.