Set Up Claude Code in Dev Containers 2026

Written by Michael Lip · Solo founder of Zovo · $400K+ on Upwork · 100% JSS Join 50+ builders · More at zovo.one

The Workflow

Create a Dev Container configuration that includes Claude Code out of the box. Every developer who opens the project in VS Code, GitHub Codespaces, or any Dev Container-compatible tool gets a working Claude Code environment with zero manual setup.

Expected time: 15 minutes Prerequisites: VS Code with Dev Containers extension (or compatible tool), Docker Desktop, Anthropic API key

Setup

1. Create the Dev Container Directory

mkdir -p .devcontainer

2. Write devcontainer.json

{
  "name": "Project with Claude Code",
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },
  "features": {
    "ghcr.io/devcontainers/features/node:1": {
      "version": "20"
    },
    "ghcr.io/devcontainers/features/git:1": {
      "version": "latest",
      "ppa": false
    },
    "ghcr.io/devcontainers/features/common-utils:2": {
      "installZsh": true,
      "configureZshAsDefaultShell": true,
      "installOhMyZsh": true
    }
  },
  "postCreateCommand": "bash .devcontainer/post-create.sh",
  "postStartCommand": "claude --version",
  "initializeCommand": "echo 'Building dev container with Claude Code...'",
  "secrets": {
    "ANTHROPIC_API_KEY": {
      "description": "Anthropic API key for Claude Code CLI"
    }
  },
  "containerEnv": {
    "CLAUDE_CODE_THEME": "dark",
    "EDITOR": "code --wait"
  },
  "customizations": {
    "vscode": {
      "settings": {
        "terminal.integrated.defaultProfile.linux": "zsh",
        "terminal.integrated.scrollback": 50000,
        "terminal.integrated.fontSize": 14
      },
      "extensions": [
        "esbenp.prettier-vscode",
        "dbaeumer.vscode-eslint",
        "bradlc.vscode-tailwindcss"
      ]
    }
  },
  "forwardPorts": [3000, 5173, 8080],
  "mounts": [
    "source=${localEnv:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached"
  ],
  "remoteUser": "vscode"
}

3. Create the Dockerfile

# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04

# Install Claude Code
RUN su vscode -c "npm install -g @anthropic-ai/claude-code" 2>&1

# Install additional language runtimes your project needs
RUN apt-get update && apt-get install -y \
    python3 python3-pip python3-venv \
    && rm -rf /var/lib/apt/lists/*

# Pre-create directories
RUN mkdir -p /home/vscode/.claude && chown vscode:vscode /home/vscode/.claude

4. Create the Post-Create Script

#!/bin/bash
# .devcontainer/post-create.sh
set -e

echo "Setting up development environment..."

# Install project dependencies
if [ -f "package.json" ]; then
    npm install
fi

if [ -f "requirements.txt" ]; then
    pip3 install -r requirements.txt
fi

# Verify Claude Code
if command -v claude &> /dev/null; then
    echo "Claude Code version: $(claude --version)"
else
    echo "ERROR: Claude Code not found. Installing..."
    npm install -g @anthropic-ai/claude-code
fi

# Check for CLAUDE.md
if [ -f "CLAUDE.md" ]; then
    echo "Found CLAUDE.md - project context will be available to Claude Code"
else
    echo "TIP: Create a CLAUDE.md file to give Claude Code project context"
fi

echo "Dev container setup complete. Run 'claude' to start."
chmod +x .devcontainer/post-create.sh

5. Configure Secrets in VS Code

# For local Dev Containers, set the env var before opening:
export ANTHROPIC_API_KEY="sk-ant-your-key-here"

# For GitHub Codespaces, set as a Codespace secret:
gh secret set ANTHROPIC_API_KEY --app codespaces --body "sk-ant-xxx"

6. Verify

# Rebuild the container: Ctrl+Shift+P → "Dev Containers: Rebuild Container"
# Open terminal in VS Code: Ctrl+`

claude --version
# Expected output:
# claude-code x.x.x

claude --print "What project am I in? List the top-level files."
# Expected output:
# Lists your project root files

Usage Example

A team dev container for a full-stack TypeScript project:

{
  "name": "Full-Stack TS + Claude Code",
  "build": { "dockerfile": "Dockerfile" },
  "features": {
    "ghcr.io/devcontainers/features/node:1": { "version": "20" },
    "ghcr.io/devcontainers/features/docker-in-docker:2": {},
    "ghcr.io/devcontainers/features/github-cli:1": {}
  },
  "postCreateCommand": "npm install -g @anthropic-ai/claude-code && npm ci",
  "secrets": {
    "ANTHROPIC_API_KEY": {
      "description": "Claude Code API key"
    },
    "DATABASE_URL": {
      "description": "PostgreSQL connection string"
    }
  },
  "containerEnv": {
    "NODE_ENV": "development"
  },
  "forwardPorts": [3000, 5432, 6379],
  "customizations": {
    "vscode": {
      "settings": {
        "terminal.integrated.profiles.linux": {
          "claude": {
            "path": "/usr/local/bin/claude",
            "icon": "robot"
          }
        }
      }
    }
  }
}

Using Claude Code inside the container:

# Open the terminal and start Claude Code
claude

# Ask it to scaffold a new API endpoint
> Create a new TRPC router for managing blog posts with:
> - list (paginated, with cursor)
> - getById
> - create (requires auth)
> - update (requires auth + ownership)
> - delete (requires auth + ownership)
> Use our existing prisma schema for the Post model.

Claude Code reads the project context from CLAUDE.md and your existing code, then generates files that match your project’s patterns:

// src/server/routers/post.ts
import { z } from "zod";
import { router, publicProcedure, protectedProcedure } from "../trpc";
import { TRPCError } from "@trpc/server";

export const postRouter = router({
  list: publicProcedure
    .input(z.object({
      cursor: z.string().nullish(),
      limit: z.number().min(1).max(100).default(20),
    }))
    .query(async ({ ctx, input }) => {
      const posts = await ctx.prisma.post.findMany({
        take: input.limit + 1,
        cursor: input.cursor ? { id: input.cursor } : undefined,
        orderBy: { createdAt: "desc" },
        include: { author: { select: { name: true, image: true } } },
      });

      let nextCursor: string | undefined;
      if (posts.length > input.limit) {
        const next = posts.pop();
        nextCursor = next?.id;
      }

      return { posts, nextCursor };
    }),
});

Common Issues

Why This Matters

Dev Containers ensure every team member has Claude Code configured identically. New developers go from git clone to productive AI-assisted coding in under 5 minutes instead of spending an hour on environment setup.