Skip to content

Development Container Setup

A new developer joins your team. They spend two days setting up their environment: installing Node.js, configuring PostgreSQL, fighting with Python version managers, and then discovering that Claude Code needs specific environment variables to work with your proxy. Dev containers eliminate this entirely — every developer gets an identical, pre-configured environment with Claude Code ready to go.

  • A production-ready devcontainer configuration with Claude Code pre-installed
  • GitHub Codespaces setup for browser-based Claude Code access
  • Patterns for sharing Claude Code configuration across containerized environments
  • Security considerations for running Claude Code in containers

Create .devcontainer/devcontainer.json in your repository:

{
"name": "Project Dev Environment",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {},
"ghcr.io/devcontainers/features/git:1": {}
},
"postCreateCommand": "npm install && npm run build",
"postStartCommand": "npm install -g @anthropic-ai/claude-code@latest",
"forwardPorts": [3000, 5432],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
},
"remoteEnv": {
"NODE_ENV": "development"
}
}

For more control, use a Dockerfile:

# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/typescript-node:20
# Install Claude Code globally
RUN npm install -g @anthropic-ai/claude-code@latest
# Install project-specific tools
RUN apt-get update && apt-get install -y \
postgresql-client \
jq \
&& rm -rf /var/lib/apt/lists/*
# Pre-configure Claude Code settings directory
RUN mkdir -p /home/node/.claude

Reference it in devcontainer.json:

{
"build": {
"dockerfile": "Dockerfile"
}
}

Codespaces provide cloud-hosted dev containers accessible from your browser or local VS Code.

{
"name": "Codespace with Claude Code",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"postStartCommand": "npm install -g @anthropic-ai/claude-code@latest",
"secrets": {
"ANTHROPIC_API_KEY": {
"description": "API key for Claude Code",
"documentationUrl": "https://console.anthropic.com/settings/keys"
}
},
"portsAttributes": {
"3000": {
"label": "Application",
"onAutoForward": "openBrowser"
}
}
}

The secrets field prompts developers to configure their API key when creating the Codespace.

Share your local Claude Code settings with the container:

{
"mounts": [
"source=${localEnv:HOME}/.claude,target=/home/node/.claude,type=bind,consistency=cached"
]
}

This shares your sessions, auto-memory, and personal settings with the container. Changes in the container are reflected on your host.

Since .claude/settings.json, .claude/commands/, and .claude/agents/ are part of your repository, they are automatically available inside the container. No additional configuration needed.

Never hardcode API keys in devcontainer.json. Use one of these approaches:

  1. Environment variable passthrough: "${localEnv:ANTHROPIC_API_KEY}"
  2. Codespace secrets: Configured per-user in GitHub settings
  3. apiKeyHelper script: Generates keys dynamically from a secrets manager

Dev containers can restrict network access:

{
"runArgs": ["--network=project-network"],
"remoteEnv": {
"HTTPS_PROXY": "http://proxy:8080"
}
}

Claude Code’s sandbox restricts file system access by default. In a container, this provides defense in depth:

{
"remoteEnv": {
"CLAUDE_CODE_SANDBOX": "1"
}
}

Claude Code not found after container rebuild: The postStartCommand runs after every container start, but the postCreateCommand only runs on creation. Put Claude Code installation in postStartCommand to ensure it survives rebuilds.

Mounted .claude directory has wrong permissions: Container users may differ from your host user. Add a postStartCommand to fix permissions: "sudo chown -R node:node /home/node/.claude".

API key not available in container terminal: Make sure you are using ${localEnv:ANTHROPIC_API_KEY} (not ${containerEnv}). The localEnv prefix passes variables from your host machine.

Sessions from host do not appear in container: Sessions are stored by directory path. If the project path differs between host and container (e.g., /Users/you/project vs /workspaces/project), sessions will not match. This is expected behavior.