"It works on my machine" is the most demoralizing phrase in software development. Mismatched Node.js versions, subtly different environment variables, dependency conflicts—I've wasted more hours on these than I care to admit.
That changed when I started combining Docker with Claude Code. Now I can 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.
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. That means fewer friction points, faster iteration.
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.
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.
version: "3.8"
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.
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.
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:
version: "3.8"
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 losing your host machine's file system.
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.
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
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 for getting Docker and Claude Code running smoothly together.
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. If Next.js hot reload is taking 5–10 seconds, moving the project to the WSL2 filesystem will fix it immediately.
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.
projects/
├── project-a/
│ ├── .devcontainer/
│ │ └── devcontainer.json # Node.js 18 + PostgreSQL 14
│ └── 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 Code configuration (CLAUDE.md), making the entire working setup portable.
{
"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.
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 monitor for 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.
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
- 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.