Docker + Claude Code gives you a sandboxed development environment where Claude Code can operate freely without touching your host machine. You get full isolation, reproducible setups via docker-compose up, and the ability to grant Claude Code broad filesystem permissions safely — because the worst case is just rebuilding a container.
"It works on my machine" is the most demoralizing phrase in software development. Mismatched Node.js versions, subtly different environment variables, dependency conflicts — every team has lost hours to these. Prisma migrations failing due to OpenSSL version mismatches, for example, is a staple in GitHub Issues.
Combining Docker with Claude Code solves this cleanly. Hand off the entire environment setup to Claude Code and get a production-equivalent dev environment in minutes. Here's how.
Why Is Claude Code + Docker Such a Powerful Combination?
Claude Code is an excellent code generation tool, but it operates directly on your host machine — installing packages, modifying config files, occupying ports. In most cases that's fine, but for large-scale refactors or exploratory changes, host-level side effects can be a problem.
Adding Docker changes the equation completely.
Complete isolation — No matter how many files Claude Code rewrites inside a container, nothing leaks to the host. Destructive changes are reversible by recreating the container. If Claude Code breaks half the imports during a refactor inside a container, docker compose down && docker compose up gets you back to square one immediately.
Guaranteed reproducibility — docker compose up gives every team member an identical environment. The "works on my machine" problem disappears.
Parity with production — Develop on the same OS image and middleware versions as production. Staging environment drift shrinks dramatically.
Safe, broad permissions for Claude Code — You can give Claude Code wide filesystem access inside a container without worrying about host damage. Anthropic's official devcontainer setup even supports --dangerously-skip-permissions for fully unattended operation, combined with firewall rules that restrict outbound traffic to whitelisted domains only.
How Do You Set Up a DevContainer for Claude Code?
VS Code's DevContainer feature is the standard approach for Docker-based development. Claude Code can read this configuration and run inside the container. Anthropic also publishes a reference devcontainer with security features baked in — use it as a starting point or customize your own.
Prerequisites
- Docker Desktop (or Docker Engine + Docker Compose)
- VS Code with the Dev Containers extension
- Claude Code CLI
Setup steps
Create the .devcontainer/ directory at your project root.
mkdir -p .devcontainer
Create .devcontainer/devcontainer.json.
{
"name": "My Project Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "22"
},
"ghcr.io/devcontainers/features/git:1": {}
},
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"bradlc.vscode-tailwindcss"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"postCreateCommand": "npm install && npm run build",
"remoteUser": "node"
}
Create .devcontainer/docker-compose.yml. Note: the version field is obsolete in Docker Compose V2 and should be omitted.
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
- node_modules:/workspace/node_modules
ports:
- "3000:3000"
environment:
- NODE_ENV=development
command: sleep infinity
volumes:
node_modules:
Create .devcontainer/Dockerfile.
FROM node:22-bookworm-slim
RUN apt-get update && apt-get install -y \
git \
curl \
&& rm -rf /var/lib/apt/lists/*
# Install Claude Code CLI
RUN npm install -g @anthropic-ai/claude-code
WORKDIR /workspace
Open the project folder in VS Code with "Reopen in Container" and the environment comes up automatically. The first build took about 3 minutes on my M2 MacBook — subsequent starts are under 10 seconds thanks to Docker's layer caching.
How Do You Get Claude Code to Generate docker-compose.yml?
Real projects often involve databases, caches, message queues, and other services. Writing the full docker-compose.yml from scratch takes time. Claude Code handles this well — I've had it generate accurate configs for projects with 5+ services on the first try.
Here's the kind of prompt that gets excellent results:
Create a docker-compose.yml for this Next.js project.
Requirements:
- Next.js 15 (Node.js 22)
- PostgreSQL 16
- Redis 7
- Development environment (hot reload enabled)
- No production config needed
- Health checks on all services
- Environment variables loaded from .env.local
A typical Claude Code output:
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
- /app/node_modules
- /app/.next
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp_dev
- REDIS_URL=redis://redis:6379
env_file:
- .env.local
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
command: npm run dev
db:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=myapp_dev
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
redis_data:
Health checks, service dependencies, named volumes — all properly configured. From there, you can iterate: "Change PostgreSQL to version 17," "Add a backup service," and Claude Code updates the file correctly.
How Do You Run Claude Code Safely Inside a Container?
Running Claude Code inside a container is primarily about containing the blast radius of destructive operations. When you ask Claude Code to "delete these files" or "refactor everything in this directory," doing that inside a container means the worst case is losing the container — not your host filesystem.
Start Claude Code inside the container
# Enter the running container
docker exec -it myproject-app-1 bash
# Run Claude Code from inside
claude
If you're using DevContainers in VS Code, the integrated terminal is already inside the container. No extra steps needed.
For fully unattended workflows (CI pipelines, batch processing), the official devcontainer supports --dangerously-skip-permissions combined with a firewall that whitelists only npm registry, GitHub, and the Claude API. This means Claude Code can run without permission prompts while still being network-isolated.
# Inside the official devcontainer with firewall enabled
claude --dangerously-skip-permissions
Passing API credentials safely
Claude Code needs your API key. Never hardcode it.
# docker-compose.yml
services:
app:
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
# .env on the host side (add to .gitignore!)
ANTHROPIC_API_KEY=sk-ant-...
Passing credentials from the host environment into the container keeps secrets out of version control and out of the Docker image.
What Do You Need to Know About Docker + Claude Code on WSL2?
On Windows with WSL2 (Windows Subsystem for Linux), there are a few important considerations. I run this exact setup daily on WSL2 Ubuntu — the performance is excellent once you avoid the common pitfall.
Recommended setup
- Use Docker Desktop for Windows with the WSL2 backend
- Keep your projects in the WSL2 filesystem (
/home/username/) - Do not place projects under
/mnt/c/(the Windows filesystem)
Mounting Windows filesystem paths into Docker volumes causes severe performance degradation. I made this mistake early on — Next.js hot reload was taking 8 seconds per save. Moving the project to ~/projects/ on the WSL2 filesystem dropped it to under 1 second. If you're already on WSL2 and wondering about Claude Code disconnection issues, check our dedicated troubleshooting guide.
Install Claude Code in WSL2
# Run inside WSL2 (Ubuntu)
sudo apt update
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
npm install -g @anthropic-ai/claude-code
VS Code + WSL2 integration
The Remote - WSL extension lets you edit WSL2 files from Windows VS Code. The Dev Containers extension also works inside WSL2. The result is a seamless Windows-native experience backed by a Linux environment.
How Do You Fully Isolate Dev Environments Per Project?
When working across multiple projects, giving each one its own DevContainer configuration creates clean, complete isolation. Even when working with different Node.js versions across projects, switching is just "Reopen in Container" with zero version conflicts.
projects/
├── project-a/
│ ├── .devcontainer/
│ │ └── devcontainer.json # Node.js 20 + PostgreSQL 16
│ └── src/
├── project-b/
│ ├── .devcontainer/
│ │ └── devcontainer.json # Node.js 22 + MySQL 8
│ └── src/
└── project-c/
├── .devcontainer/
│ └── devcontainer.json # Python 3.12 + Redis
└── src/
Each project's DevContainer can include its own CLAUDE.md configuration, making the entire working setup portable. Project-specific prompts, forbidden patterns, and coding conventions travel with the repo.
{
"postCreateCommand": "npm install && echo 'Dev environment ready for Claude Code'"
}
The real payoff comes when a new team member joins. git clone → open in VS Code → "Reopen in Container." That's the entire onboarding process. Claude Code runs identically for everyone.
How Do You Configure MCP Servers Inside a Container?
MCP (Model Context Protocol) servers can also run inside the container, sandboxing Claude Code's tool access along with everything else.
// .claude/settings.json (inside the container)
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/workspace"
]
},
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://postgres:password@db:5432/myapp_dev"
]
}
}
}
Restricting the filesystem server to /workspace limits Claude Code's file access to the project directory only.
The postgres server enables queries like "check the schema of the users table" or "find the N+1 query problem in these endpoints" to be handled by Claude Code directly against your actual database. I use this combination on 32blog — Claude Code can read the database schema and generate Prisma-based APIs without me describing the data model manually.
How Do You Use Claude Code to Prevent Dev/Prod Drift?
Dev/prod drift usually happens gradually: a convenience setting added during development never makes it to production. Claude Code can actively detect this.
Compare docker-compose.yml (development) with
k8s/deployment.yaml (production).
Look for differences in environment variables,
port configurations, and health check settings.
Present any discrepancies in a table.
You can also ask Claude Code to generate and maintain your CI/CD pipeline.
Create .github/workflows/deploy.yml:
- Build Docker image and push to GHCR
- Deploy using docker-compose.prod.yml
- Run health checks after deployment
- Send Slack notification on failure
By delegating environment configuration to Claude Code, you get continuous detection of the subtle drift that humans tend to overlook.
How Do You Integrate CI/CD Pipelines with Docker Dev Environments?
When Docker images differ between dev and CI environments, you get "works locally but fails in CI." Claude Code can unify CI and dev configurations using multi-stage Dockerfiles.
Multi-stage Dockerfile generation prompt:
Write a Dockerfile for this project with these conditions:
- base stage: Node.js 22 Alpine + shared dependencies
- dev stage: inherits base, includes devDependencies, hot reload
- ci stage: inherits base, run tests and build
- prod stage: inherits base, built assets only
Generated Dockerfile structure:
# base
FROM node:22-alpine AS base
WORKDIR /app
COPY package*.json ./
# dev
FROM base AS dev
RUN npm ci
CMD ["npm", "run", "dev"]
# ci
FROM base AS ci
RUN npm ci
COPY . .
RUN npm run build
RUN npm test
CMD ["echo", "CI passed"]
# prod
FROM base AS prod
RUN npm ci --omit=dev
COPY --from=ci /app/dist ./dist
CMD ["node", "dist/server.js"]
GitHub Actions integration:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build --target ci -t app-ci .
- run: docker run app-ci
Using different stages of the same Dockerfile for DevContainers and CI/CD structurally eliminates "environment drift" problems. If you're setting up a Next.js project with Claude Code, this multi-stage approach is especially effective.
Frequently Asked Questions
Does Claude Code work inside Docker on ARM-based Macs (M1/M2/M3)?
Yes. Docker Desktop for Apple Silicon runs containers via Rosetta 2 or native ARM images. The node:22-bookworm-slim and node:22-alpine images both have ARM64 variants, so Claude Code installs and runs without issues. Performance is comparable to running natively.
Can I use Claude Code with Docker Compose without VS Code?
Absolutely. DevContainers are just a VS Code convenience layer. You can run docker compose up, then docker exec -it <container> bash, and launch claude directly. Any terminal emulator works — VS Code is not required.
How much disk space does a Claude Code DevContainer need?
A basic Node.js + Claude Code container image is about 500MB. Adding PostgreSQL and Redis brings the total to around 1.2GB. Named volumes for node_modules and database data add more over time. Budget 2-3GB per project for comfortable development.
Is --dangerously-skip-permissions safe inside a container?
Inside a properly configured container with firewall rules (like the official devcontainer), the risk is significantly reduced. Claude Code can only access the container's filesystem and whitelisted network destinations. However, it can still read anything mounted into the container — so don't mount sensitive host directories.
Can I share a DevContainer configuration across a team?
Yes — that's one of the main benefits. Commit the .devcontainer/ directory to your repository. Every team member who opens the project in VS Code gets prompted to "Reopen in Container," and they get an identical environment. Claude Code configuration (CLAUDE.md) travels with the repo too.
How do I update Claude Code inside a running container?
Run npm update -g @anthropic-ai/claude-code inside the container. For a permanent update, change the version in your Dockerfile and rebuild: docker compose build --no-cache app.
What's the performance overhead of running Claude Code in Docker vs natively?
On Linux and macOS, the overhead is negligible — Docker uses the host kernel directly. On Windows with WSL2, there's a small overhead for the WSL translation layer, but Claude Code's API calls (the bottleneck) are network-bound, not CPU-bound. You won't notice a difference in practice.
Can I run multiple Claude Code instances in separate containers simultaneously?
Yes. Each container is fully isolated, so you can run Claude Code in container A working on a frontend task while container B handles a backend refactor. Check our guide on running multiple Claude Code instances for detailed patterns.
Wrapping Up
Combining Docker with Claude Code gives you something valuable: an environment where you can make bold requests safely.
- Container isolation limits the impact of Claude Code's destructive changes to the container itself
- DevContainer configs let every team member run Claude Code in identical environments
- Complex docker-compose setups can be generated by Claude Code in minutes
- The official devcontainer adds firewall rules for fully unattended operation
- WSL2 users get the same benefits as long as projects live in the WSL2 filesystem
To get started: create a .devcontainer/ directory and ask Claude Code to generate devcontainer.json and docker-compose.yml for your project. You'll have a production-equivalent development environment within fifteen minutes.
If you run into issues, our Claude Code troubleshooting guide covers common Docker-related errors. And if you're looking to optimize your Claude Code workflow further, the token cost reduction guide shows how to keep API costs under control even with container-based development.