run-claude-docker
Dockerized Claude Code environment — isolated, persistent container with pre-configured Unsplash, Context7, and Playwright MCP servers
This script provides a secure, isolated Docker environment for running Claude Code, bundling essential development tools and pre-configured MCP servers like Unsplash, Context7, and Playwright. It automates Docker image building and container management, ensuring a consistent and persistent workspace for Claude Code interactions. Authentication forwarding and read-only mounts enhance security while maintaining ease of use.
- Standalone script with embedded Dockerfile
- Pre-configured Unsplash, Context7, Playwright MCP servers
- Automated Docker image build and container management
- Persistent container for faster startup and state preservation
- Host system protection with read-only mounts and user isolation
README
View on GitHub ↗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()functionTest 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 --rebuildExport 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
Similar mcp servers
ruflo
Multi-agent orchestration MCP server for Claude Code — deploys swarms, coordinates workflows, learns from outcomes
claude-task-master
MCP server for AI task management — streamlines development workflows with Claude and other AI chats
n8n-mcp
MCP server for n8n workflow automation — provides AI assistants deep access to 1,500+ n8n nodes and templates
ccusage
MCP server for Claude Code usage — real-time token and cost analysis from local JSONL files