Claude Code Docker 容器化方案

基于双层镜像架构的快速构建方案

方案概述

本项目通过 Docker 容器化 Claude Code CLI,提供一致、可移植的开发环境。

核心目标

  1. 快速构建 - 通过预构建基础镜像,重建时间从 5-10 分钟降至 10-30 秒
  2. 环境一致 - 任何机器上都是相同的工具版本和配置
  3. 安全隔离 - Claude Code 的操作被限制在容器内
  4. 开袋即用 - 预装所有依赖(Node.js、Bun、Chromium、Git 等)

双层镜像架构

┌─────────────────────────────────────┐
│ docker-claude:latest (应用镜像)      │  ← 只包含 skills,构建快 (~10 秒)
│ - 复制 skills 目录                    │
│ - 用户配置和环境变量                  │
└─────────────────────────────────────┘
           ↑ 基于
┌─────────────────────────────────────┐
│ docker-claude-base:with-deps        │  ← 预构建基础镜像,一次构建永久缓存
│ - Ubuntu 24.04 LTS                   │
│ - 系统包 (git, curl, chromium 等)     │
│ - Node.js 24 LTS                     │
│ - Bun (latest)                       │
│ - Claude Code CLI (latest)           │
│ - 非 root 用户 claude                 │
└─────────────────────────────────────┘

镜像大小

镜像 大小 说明
docker-claude-base:with-deps ~1.37 GB 包含所有重依赖
docker-claude:latest ~1.37 GB 仅增加 skills 目录

构建时间对比

场景 传统构建 优化后
首次构建 ~8-12 分钟 ~8-12 分钟(相同)
重建(缓存命中) ~5-8 分钟 ~10-30 秒
基础镜像变化 ~8-12 分钟 ~5-8 分钟(仅重建基础层)

与官方沙箱对比

官方沙箱 (Sandbox)

Claude Code 内置的轻量级隔离环境,基于 macOS Sandbox 或 Linux seccomp/namespace。

架构图:

用户终端
   ↓
Claude Code CLI
   ↓
官方沙箱 (限制文件系统访问、网络等)
   ↓
宿主机工具 (git, npm, docker 等)

Docker 容器方案

在 Docker 容器中运行完整的 Claude Code 环境。

架构图:

用户终端
   ↓
docker exec 进入容器
   ↓
容器内的 Claude Code CLI
   ↓
容器内工具链 (完全可控的环境)
   ↓
挂载的宿主机卷 (通过 -v 映射)

详细对比表

维度 官方沙箱 Docker 容器
隔离性 ⭐⭐ 弱 - 仍是宿主机环境 ⭐⭐⭐⭐⭐ 强 - 容器隔离
启动速度 ⭐⭐⭐⭐⭐ 秒级 - 无需容器 ⭐⭐⭐⭐ 秒级(容器已存在)
环境一致性 ⭐⭐ 依赖宿主机配置 ⭐⭐⭐⭐⭐ 完全一致
安全性 ⭐⭐⭐ 中等 - 沙箱限制 ⭐⭐⭐⭐⭐ 高 - 容器隔离
配置复杂度 ⭐⭐⭐⭐⭐ 简单 - 开箱即用 ⭐⭐⭐ 中等 - 需 Docker 知识
可定制性 ⭐⭐ 受限 - 依赖宿主机 ⭐⭐⭐⭐⭐ 完全可控
磁盘占用 ⭐⭐⭐⭐⭐ 小 - 无额外镜像 ⭐⭐⭐ 较大 - ~1.37GB
团队协作 ⭐⭐ 配置可能不同 ⭐⭐⭐⭐⭐ 镜像统一
工具预装 ⭐⭐ 需自行安装 ⭐⭐⭐⭐⭐ 全部预装
跨平台 ⭐⭐⭐ 依赖系统支持 ⭐⭐⭐⭐ 有 Docker 即可

优缺点总结

官方沙箱

优点:

  • ✅ 启动快 - 无需启动容器,秒级响应
  • ✅ 配置简单 - 无需 Docker 配置,开箱即用
  • ✅ 原生性能 - 直接使用宿主机工具,无虚拟化开销
  • ✅ 文件访问方便 - 可以直接访问项目文件,无需挂载卷

缺点:

  • ❌ 隔离性弱 - 仍是宿主机环境,有安全风险
  • ❌ 环境依赖宿主机 - 需要预先安装 Node.js、Bun、Git 等
  • ❌ 权限受限 - 某些操作(如 Docker in Docker)无法执行
  • ❌ 环境不一致 - 不同机器可能有不同配置

Docker 容器

优点:

  • ✅ 强隔离性 - 容器内操作不影响宿主机
  • ✅ 环境一致 - 任何机器上都是相同的工具版本
  • ✅ 预装所有工具 - Node.js、Bun、Chromium、Git 等全部内置
  • ✅ 可定制性强 - 可以安装任意工具,修改系统配置
  • ✅ 快速上手 - 新人只需拉取镜像即可开始工作
  • ✅ 配置持久化 - 通过卷挂载保存配置,容器可随意重建

缺点:

  • ❌ 启动稍慢 - 需要启动容器(但已优化到秒级)
  • ❌ 镜像较大 - 约 1.37GB(但缓存后构建很快)
  • ❌ 需要 Docker - 宿主机必须安装 Docker
  • ❌ 文件访问需挂载 - 需要通过 -v 挂载卷访问宿主机文件
  • ❌ 网络配置复杂 - 某些场景需要配置网络模式

使用指南

目录结构

docker-optimized/
├── Dockerfile.base      # 预构建基础镜像(重依赖)
├── Dockerfile           # 应用镜像(轻量,仅 skills)
├── docker-compose.yml   # Docker Compose 配置
├── build.sh             # 自动化构建脚本
├── .dockerignore        # 构建排除文件
├── README.md            # 快速开始指南
└── skills/              # Claude Code Skills 目录
    ├── claude-mem/
    ├── everything-claude-code/
    └── superpowers/

核心文件详解

1. Dockerfile.base(预构建基础镜像)

基础镜像包含所有重量级依赖,一次构建永久缓存:

# ============================================
# Pre-built Base Image for Claude Code Docker
# ============================================
# This image contains all heavy dependencies:
# - Ubuntu 24.04 base (LTS)
# - System packages (git, curl, chromium, etc.)
# - Node.js 24 LTS
# - Bun (latest)
# - Claude Code CLI (latest)
#
# Build this image once and tag it locally for fast rebuilds
# ============================================

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8

# ============================================
# Install system dependencies
# ============================================
RUN apt-get update && apt-get install -y --no-install-recommends \
    # Basic tools
    git curl ca-certificates jq bc gpg unzip \
    # Build tools
    build-essential \
    # Common utilities
    vim nano wget htop tree \
    # Chromium dependencies
    libnss3 libatk-bridge2.0-0 libxss1 libgtk-3-0 \
    libx11-xcb1 libdrm2 libgbm1 libasound2t64 \
    libxcomposite1 libxdamage1 libxfixes3 \
    libpango-1.0-0 libcairo2 libatk1.0-0 \
    # Other dependencies
    fonts-liberation libappindicator3-1 libu2f-udev \
    xdg-utils libvulkan1 \
    # Chromium browser
    chromium-browser chromium-chromedriver \
    # Cleanup
    && rm -rf /var/lib/apt/lists/*

# ============================================
# Install Node.js 24 LTS
# ============================================
RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
    && apt-get install -y --no-install-recommends nodejs \
    && rm -rf /var/lib/apt/lists/*

# ============================================
# Install Bun (latest)
# ============================================
ENV BUN_INSTALL="/usr/local"
ENV PATH="/usr/local/bin:$PATH"
RUN curl -fsSL https://bun.sh/install | bash

# ============================================
# Install Claude Code CLI
# ============================================
RUN npm install -g @anthropic-ai/claude-code

# ============================================
# Set Chromium environment variables
# ============================================
ENV CHROME_BIN=/usr/bin/chromium-browser
ENV CHROMIUM_BIN=/usr/bin/chromium-browser

# ============================================
# Create non-root user
# ============================================
RUN useradd -m -s /bin/bash claude \
    && mkdir -p /home/claude/.claude /home/claude/.gstack \
    && chown -R claude:claude /home/claude \
    && chmod 1777 /tmp

# ============================================
# Set environment variables
# ============================================
ENV HOME=/home/claude
ENV USER=claude
ENV SHELL=/bin/bash

# Working directory
WORKDIR /workspace

CMD ["/bin/bash"]

2. Dockerfile(应用镜像)

应用镜像基于基础镜像构建,仅复制 skills 目录:

# ============================================
# Stage 1: Builder - Prepare skills
# ============================================
FROM docker-claude-base:with-deps AS builder

WORKDIR /build

# Copy skill plugins from local context
COPY skills/ ./skills/

# ============================================
# Stage 2: Runtime - Copy skills and configure
# ============================================
FROM docker-claude-base:with-deps AS runtime

# Copy skills from builder stage
COPY --from=builder /build/skills /home/claude/.claude/skills/

# Set ownership
RUN chown -R claude:claude /home/claude/.claude/skills

# ============================================
# Environment variables (overridable at runtime)
# ============================================

# Claude / Anthropic
ENV ANTHROPIC_API_KEY=""
ENV ANTHROPIC_BASE_URL="https://api.anthropic.com"

# OpenAI compatible
ENV OPENAI_API_KEY=""
ENV OPENAI_BASE_URL="https://api.openai.com/v1"

# Alibaba DashScope
ENV DASHSCOPE_API_KEY=""
ENV DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"

# DeepSeek
ENV DEEPSEEK_API_KEY=""
ENV DEEPSEEK_BASE_URL="https://api.deepseek.com/v1"

# Moonshot (Kimi)
ENV MOONSHOT_API_KEY=""
ENV MOONSHOT_BASE_URL="https://api.moonshot.cn/v1"

# Zhipu AI
ENV ZHIPU_API_KEY=""
ENV ZHIPU_BASE_URL="https://open.bigmodel.cn/api/paas/v4"

# SiliconFlow
ENV SILICONFLOW_API_KEY=""
ENV SILICONFLOW_BASE_URL="https://api.siliconflow.cn/v1"

# Default model
ENV DEFAULT_MODEL="claude-3-5-sonnet-20241022"

# Terminal
ENV TERM=xterm-256color

WORKDIR /workspace
USER claude

CMD ["/bin/bash"]

3. docker-compose.yml

Docker Compose 配置文件,支持多服务商 API 密钥:

services:
  claude:
    build:
      context: .
      dockerfile: Dockerfile
      target: runtime

    container_name: claude-code

    # Interactive mode
    stdin_open: true
    tty: true

    # Volume mounts
    volumes:
      # Working directory
      - ./data/workspace:/workspace
      # Claude config persistence
      - ./data/claude-config:/home/claude/.claude
      # Gstack config persistence
      - ./data/gstack-config:/home/claude/.gstack
      # Optional: Mount host SSH keys
      - ~/.ssh:/home/claude/.ssh:ro
      # Optional: Mount host git config
      - ~/.gitconfig:/home/claude/.gitconfig:ro

    # Working directory
    working_dir: /workspace

    # Environment variables (loaded from .env file)
    environment:
      # Claude / Anthropic
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
      - ANTHROPIC_BASE_URL=${ANTHROPIC_BASE_URL:-https://api.anthropic.com}

      # OpenAI compatible
      - OPENAI_API_KEY=${OPENAI_API_KEY:-}
      - OPENAI_BASE_URL=${OPENAI_BASE_URL:-https://api.openai.com/v1}

      # Alibaba DashScope
      - DASHSCOPE_API_KEY=${DASHSCOPE_API_KEY:-}
      - DASHSCOPE_BASE_URL=${DASHSCOPE_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}

      # DeepSeek
      - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-}
      - DEEPSEEK_BASE_URL=${DEEPSEEK_BASE_URL:-https://api.deepseek.com/v1}

      # Moonshot (Kimi)
      - MOONSHOT_API_KEY=${MOONSHOT_API_KEY:-}
      - MOONSHOT_BASE_URL=${MOONSHOT_BASE_URL:-https://api.moonshot.cn/v1}

      # Zhipu AI
      - ZHIPU_API_KEY=${ZHIPU_API_KEY:-}
      - ZHIPU_BASE_URL=${ZHIPU_BASE_URL:-https://open.bigmodel.cn/api/paas/v4}

      # SiliconFlow
      - SILICONFLOW_API_KEY=${SILICONFLOW_API_KEY:-}
      - SILICONFLOW_BASE_URL=${SILICONFLOW_BASE_URL:-https://api.siliconflow.cn/v1}

      # Default model
      - DEFAULT_MODEL=${DEFAULT_MODEL:-claude-3-5-sonnet-20241022}

      # Terminal
      - TERM=${TERM:-xterm-256color}

    # Network mode (host mode for easy access to local services)
    network_mode: host

    # Startup command
    command: /bin/bash

4. build.sh(自动化构建脚本)

自动化构建脚本,支持智能缓存检测:

#!/bin/bash
set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Configuration
BASE_IMAGE="docker-claude-base:with-deps"
APP_IMAGE="docker-claude:latest"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Functions
print_header() {
    echo -e "\n${BLUE}========================================${NC}"
    echo -e "${BLUE}$1${NC}"
    echo -e "${BLUE}========================================${NC}\n"
}

print_success() {
    echo -e "${GREEN}$1${NC}"
}

print_warning() {
    echo -e "${YELLOW}$1${NC}"
}

print_error() {
    echo -e "${RED}$1${NC}"
}

# Check if base image exists locally
check_base_image() {
    if docker image inspect "$BASE_IMAGE" &> /dev/null; then
        return 0
    else
        return 1
    fi
}

# Build the base image
build_base_image() {
    print_header "Step 1: Building Base Image"
    echo "Base image: $BASE_IMAGE"
    echo "This image contains:"
    echo "  - Ubuntu 24.04"
    echo "  - System packages (git, curl, chromium, etc.)"
    echo "  - Node.js 24 LTS"
    echo "  - Bun 1.3.11"
    echo "  - Claude Code CLI"
    echo ""
    echo "This takes ~5-10 minutes on first build, then cached."
    echo ""

    docker build -t "$BASE_IMAGE" -f Dockerfile.base .

    print_success "Base image built: $BASE_IMAGE"

    # Show image size
    local size=$(docker image inspect "$BASE_IMAGE" --format='{{.Size}}' | awk '{printf "%.2f GB\n", $1/1024/1024/1024}')
    echo "  Image size: $size"
}

# Build the application image
build_app_image() {
    print_header "Step 2: Building Application Image"
    echo "Application image: $APP_IMAGE"
    echo "This image layers skills on top of the base image."
    echo ""

    docker build -t "$APP_IMAGE" --build-arg BUILDKIT_INLINE_CACHE=1 .

    print_success "Application image built: $APP_IMAGE"

    # Show image size
    local size=$(docker image inspect "$APP_IMAGE" --format='{{.Size}}' | awk '{printf "%.2f GB\n", $1/1024/1024/1026}')
    echo "  Image size: $size"
}

# Show build statistics
show_stats() {
    print_header "Build Statistics"

    echo "Local images:"
    docker images | grep -E "(docker-claude-base|docker-claude:)" || true
    echo ""
}

# Main execution
main() {
    cd "$SCRIPT_DIR"

    print_header "Docker Claude Code - Build Script"
    echo "Directory: $SCRIPT_DIR"
    echo ""

    # Check for skills directory
    if [ ! -d "../skills" ]; then
        print_error "skills/ directory not found in parent directory"
        echo "Please ensure skills/ exists at: $SCRIPT_DIR/../skills/"
        exit 1
    fi

    # Copy skills to local context
    print_header "Preparing Build Context"
    echo "Copying skills from parent directory..."

    if [ -d "./skills" ]; then
        rm -rf "./skills"
    fi
    cp -r "../skills" "./skills"
    print_success "Skills copied to ./skills/"

    # Check if base image exists
    if check_base_image; then
        print_success "Base image found: $BASE_IMAGE"
        echo "Skipping base image build, using cached version."
    else
        print_warning "Base image not found, building now..."
        build_base_image
    fi

    # Build application image
    build_app_image

    # Show statistics
    show_stats

    print_header "Build Complete!"
    echo "To start the container:"
    echo "  docker-compose up -d"
    echo ""
    echo "To attach to the container:"
    echo "  docker exec -it claude-code /bin/bash"
    echo ""
    echo "To rebuild (base image cached):"
    echo "  ./build.sh"
    echo ""
}

# Run main function
main "$@"

5. .dockerignore

构建时排除的文件:

# Git
.git
.gitignore

# Claude config
.claude
CLAUDE.md

# Documentation
*.md
docs/

# Environment files
.env
.env.*
!.env.example

# Build artifacts
docker-optimized/
*.log

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Test and coverage
coverage/
*.test
*.spec

# Temporary files
tmp/
temp/
*.tmp

6. .env.example(环境变量示例)

API 密钥配置模板(已脱敏):

# ============================================
# Claude Code Container Environment Variables
# Copy to .env and fill in your API Keys
# ============================================

# ============================================
# Anthropic Claude (Native Claude Code support)
# Get: https://console.anthropic.com
# ============================================
ANTHROPIC_API_KEY=sk-ant-xxx
ANTHROPIC_BASE_URL=https://api.anthropic.com

# ============================================
# OpenAI Compatible (Fallback)
# Get: https://platform.openai.com/api-keys
# ============================================
OPENAI_API_KEY=sk-xxx
OPENAI_BASE_URL=https://api.openai.com/v1

# ============================================
# Domestic Cloud Provider API Keys (Fill as needed)
# ============================================

# Alibaba Cloud DashScope (Qwen series)
# Get: https://dashscope.aliyun.com/api-key
DASHSCOPE_API_KEY=sk-xxx
DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1

# DeepSeek
# Get: https://platform.deepseek.com/api_keys
DEEPSEEK_API_KEY=sk-xxx
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1

# Moonshot (Kimi)
# Get: https://platform.moonshot.cn/console/api-keys
MOONSHOT_API_KEY=sk-xxx
MOONSHOT_BASE_URL=https://api.moonshot.cn/v1

# Zhipu AI (GLM series)
# Get: https://open.bigmodel.cn/usercenter/apikeys
ZHIPU_API_KEY=xxx.xxx
ZHIPU_BASE_URL=https://open.bigmodel.cn/api/paas/v4

# SiliconFlow
# Get: https://cloud.siliconflow.cn/account/ak
SILICONFLOW_API_KEY=sk-xxx
SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1

# ============================================
# Default Model Configuration
# ============================================
DEFAULT_MODEL=claude-3-5-sonnet-20241022

# ============================================
# Terminal Configuration
# ============================================
TERM=xterm-256color

快速开始

# 1. 进入目录
cd docker-optimized

# 2. 首次构建(基础镜像 + 应用镜像)
./build.sh

# 3. 启动容器
docker-compose up -d

# 4. 附加到容器
docker exec -it claude-code /bin/bash

日常重建(缓存命中)

# 基础镜像已缓存,重建只需 10-30 秒
./build.sh

# 或直接使用 docker-compose
docker-compose build

环境变量配置

通过 .env 文件配置 API 密钥:

# 复制示例配置
cp ../.env.example .env

# 编辑配置(替换为你的 API 密钥)
vim .env

# 启动时自动加载
docker-compose up -d

数据持久化

volumes:
  - ./data/workspace:/workspace           # 工作目录
  - ./data/claude-config:/home/claude/.claude  # Claude 配置
  - ./data/gstack-config:/home/claude/.gstack  # Gstack 配置

所有数据持久化到 ./data/ 目录,容器删除后数据不丢失。

推荐场景

选择 官方沙箱 如果:

  • ✅ 个人使用,快速测试
  • ✅ 宿主机环境已经配置完善
  • ✅ 不需要特殊工具或系统权限
  • ✅ 不想依赖 Docker

选择 Docker 容器 如果:

  • ✅ 团队协作,需要统一环境
  • ✅ 需要特定版本的工具(如 Node.js 24、Bun 最新版)
  • ✅ 关心安全性和隔离性
  • ✅ 经常在不同机器间切换
  • ✅ 需要访问 Chromium 等复杂依赖(如 E2E 测试)
  • ✅ 想要"开箱即用"的体验

故障排除

构建失败

# 清理构建缓存
docker builder prune -f

# 重新构建
./build.sh

基础镜像损坏

# 删除并重建基础镜像
docker rmi docker-claude-base:with-deps
docker build -t docker-claude-base:with-deps -f Dockerfile.base .

容器无法启动

# 查看容器日志
docker logs claude-code

# 删除容器重新创建
docker rm -f claude-code
docker-compose up -d

结论

对于需要环境一致性安全性团队协作的场景,Docker 容器方案是更好的选择。虽然需要额外的 Docker 配置和镜像存储空间,但通过双层镜像架构和优化后的构建流程,已经将重建时间从 5-10 分钟降至 10-30 秒,提供了优秀的开发体验。

官方沙箱更适合临时测试或快速原型开发,但对于生产环境或团队使用,Docker 容器方案的优势更加明显。


参考资料:ANALYSIS.md