Use Cases (更新: 2026/6/1)

Claude Code Docker Compose 实战指南:本地 App、Postgres、Redis 与 Worker

用 Claude Code 和 Docker Compose 搭建 App、Postgres、Redis、worker 的本地开发环境。

Claude Code Docker Compose 实战指南:本地 App、Postgres、Redis 与 Worker

Docker Compose 可以把 Web app、PostgreSQL、Redis 和后台 worker 放进同一份本地开发蓝图里。Docker 的 Compose 文档 把它描述为定义并运行多容器应用的工具,服务、网络、卷都可以通过一个 YAML 文件管理。

这正是它适合 Claude Code 的原因。与其只说“帮我做一个 Docker 环境”,不如把 compose.yamlDockerfile.env.exampleMakefile 放进仓库,让 Claude Code 基于真实文件审查。这样更容易复现,也更容易让团队维护。

Masa 在一个小型 Next.js + queue worker 项目里验证过这个模式。真正节省时间的不是花哨提示词,而是提前决定好数据库等待、Redis 持久化、node_modules volume、migration/test 命令和 CI 的边界。

本文会给出可复制的 app + PostgreSQL + Redis + worker 示例。Compose 非常适合本地开发、集成测试和新人 onboarding;但生产环境需要单独评估编排、安全、secret、监控、备份和成本。

架构图

flowchart LR
  Dev["Developer"] --> App["app: web server"]
  App --> Pg["postgres: database"]
  App --> Redis["redis: cache and queue"]
  Worker["worker: background jobs"] --> Pg
  Worker --> Redis
  App --> Volume["named volume: node_modules"]
  Pg --> PgVol["named volume: postgres_data"]
  Redis --> RedisVol["named volume: redis_data"]

app 负责 Web 服务,worker 负责邮件、webhook、图片处理或队列任务。postgresredis 都加上 healthcheck,避免只是容器启动了、服务却还不能连接。

语法细节建议参考 Compose file referenceservices reference。让 Claude Code 审查时也把这两份官方文档作为依据,可以减少旧版 docker-compose 示例带来的误导。

使用场景对比

场景Compose 的优势注意点
本地开发一个命令启动 app、DB、Redis、worker不同 OS 的文件挂载性能不同
集成测试可以按需创建测试 DB 和 RedisCI 里要明确端口和缓存策略
新人加入.env.examplemake setup 固定步骤示例文件不能包含真实 secret
生产环境小型内部工具有时可作为候选必须评估编排、安全、恢复、监控和成本

生产边界不能忽略。Compose 很适合在开发者机器上创建同样的工作台,但生产环境应与 ECS、Kubernetes、Cloud Run、Fly.io、Render 或现有平台比较。可以让 Claude Code 列出迁移约束,而不是默认把本地文件当部署方案。

可复制的 compose.yaml

示例假设你使用 Node.js 或 Next.js。请把 npm run devnpm run worker:dev、migration 命令替换为你项目里的脚本。

# compose.yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    command: npm run dev -- --hostname 0.0.0.0
    ports:
      - "3000:3000"
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
      REDIS_URL: redis://redis:6379
    volumes:
      - .:/workspace
      - node_modules:/workspace/node_modules
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "node -e \"fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\""]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 20s

  worker:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    command: npm run worker:dev
    env_file:
      - .env
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public
      REDIS_URL: redis://redis:6379
    volumes:
      - .:/workspace
      - node_modules:/workspace/node_modules
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  postgres:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    env_file:
      - .env
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./docker/postgres/init:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--appendonly", "yes"]
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

volumes:
  node_modules:
  postgres_data:
  redis_data:

这里有三个关键点。第一,容器之间用服务名访问,所以 app 应连接 postgres:5432redis:6379,不是 localhost。第二,node_modules 使用 named volume,避免源码 bind mount 覆盖容器内依赖。第三,Postgres healthcheck 里的双美元符号是为了让变量在容器 shell 中展开,而不是被 Compose 提前替换。

Dockerfile

一个 Dockerfile 内分出 dev、build、production stage,通常比维护多份 Dockerfile 更稳。

# Dockerfile
# syntax=docker/dockerfile:1

FROM node:22-alpine AS base
WORKDIR /workspace
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci

FROM base AS dev
EXPOSE 3000
CMD ["npm", "run", "dev", "--", "--hostname", "0.0.0.0"]

FROM base AS build
COPY . .
RUN npm run build

FROM node:22-alpine AS production
WORKDIR /workspace
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /workspace/.next ./.next
COPY --from=build /workspace/public ./public
USER node
EXPOSE 3000
CMD ["npm", "start"]

dev stage 不复制源码,因为 Compose 会通过 volume 挂载。build stage 则复制完整仓库,保证 CI 和生产镜像不依赖本机文件状态。

.env.example

提交 .env.example,不要提交 .env。示例文件只展示配置形状,不放真实凭据。

# .env.example
POSTGRES_USER=app
POSTGRES_PASSWORD=app_password
POSTGRES_DB=app_development

DATABASE_URL=postgresql://app:app_password@postgres:5432/app_development?schema=public
REDIS_URL=redis://redis:6379
NODE_ENV=development
PORT=3000

env_file 是传给容器的变量;Compose 文件内的变量替换也会读取项目根目录的 .env。这两个概念相近但不完全一样,最好保持命名和值一致。

Makefile 与一次性命令

把常用命令固定下来,可以减少口头说明。

COMPOSE = docker compose --env-file .env -f compose.yaml

.PHONY: setup up up-d down restart logs ps app-shell db-shell redis-cli migrate seed test lint clean

setup:
	cp .env.example .env
	$(COMPOSE) build

up:
	$(COMPOSE) up --build

up-d:
	$(COMPOSE) up -d --build

down:
	$(COMPOSE) down

restart:
	$(COMPOSE) restart app worker

logs:
	$(COMPOSE) logs -f app worker postgres redis

ps:
	$(COMPOSE) ps

app-shell:
	$(COMPOSE) exec app sh

db-shell:
	$(COMPOSE) exec postgres psql -U app -d app_development

redis-cli:
	$(COMPOSE) exec redis redis-cli

migrate:
	$(COMPOSE) run --rm app npm run db:migrate

seed:
	$(COMPOSE) run --rm app npm run db:seed

test:
	$(COMPOSE) run --rm app npm test

lint:
	$(COMPOSE) run --rm app npm run lint

clean:
	$(COMPOSE) down --volumes --remove-orphans

exec 用于已启动的容器,run --rm 用于一次性任务,例如 lint、test、migration、seed。这个区分能让本地命令更接近 CI。

Claude Code 审查提示词

Claude Code common workflows 强调把日常开发拆成理解、修改、测试、审查等小任务。Compose 审查也应该这样做。

请审查这个仓库的 Docker Compose 设置。

文件:
- compose.yaml
- Dockerfile
- .env.example
- package.json
- 如果存在,也检查 CI workflow 文件

检查:
1. app + postgres + redis + worker 是否能在本地运行
2. healthcheck 和 depends_on 是否使用合理
3. named volume 和 bind mount 的区分是否安全
4. .env.example 是否包含真实 secret
5. migrate、seed、test、lint 的一次性命令是否齐全
6. CI 中可能出现的端口、缓存、权限、启动等待问题
7. 如果要用于生产,必须额外审查哪些项目

约束:
- 遵循当前框架和 package manager
- 大型重构只提出建议
- 如果修改文件,请说明原因和验证命令

可以把这个提示词放在 CLAUDE.md 附近,作为团队审查标准。相关内容还可以阅读 Dev Container 指南CI/CD 设置指南

实用场景

第一个场景是新人第一天设置环境。复制 .env.example 后执行 make up,app、DB、Redis、worker 都能启动,README 会短很多。

第二个场景是本地验证队列任务。邮件、图片处理、计费 webhook、通知 fan-out 都不应该假装由 Web server 完成。把 worker 放进 Compose 后,可以更真实地复现 job。

第三个场景是集成测试。很多问题在 SQLite 替代测试中通过,却在 Postgres 上失败。使用 Compose 管理 Postgres 和 Redis,可以更早发现 SQL 方言、migration 和队列行为差异。

第四个场景是让 Claude Code 做基础设施差分审查。人类很容易漏看 localhost、旧 volume、缺少 healthcheck 或示例 secret。模板化提示词可以让审查粒度稳定。

常见坑

最常见的错误是在 app 容器里连接 localhost。Compose 网络里服务名就是 DNS 名,应使用 postgresredis

第二个错误是把 depends_on 当作完整的就绪保证。condition: service_healthy 很有用,但 app 仍然应该有数据库连接重试,worker 也不能早于 migration 执行关键任务。

旧 named volume 也会制造混乱。schema 变了但 postgres_data 还在时,本地状态可能和仓库不一致。需要重测时使用 make clean,但要知道它会删除本地数据。

不要把真实 API key 放进 .env.example。示例值用 app_passwordreplace_me,生产 secret 放到 Docker secrets、云 secret manager 或 CI secret store。

最后,不要默认把本地 Compose 文件当生产方案。生产环境需要 TLS、网络暴露、DB 备份、Redis 持久化、监控、漏洞扫描、镜像来源、权限边界和成本评估。

ClaudeCodeLab 教材与咨询

如果要把这套方案落到自己的仓库,可以先用 ClaudeCodeLab 的产品与模板 统一 CLAUDE.md、审查提示词和 setup runbook。如果难点是团队导入、Docker Desktop 差异、CI/CD、权限边界,或判断 Compose 到哪里为止,请使用 Claude Code 培训与咨询

本文使用的官方参考包括 Docker ComposeCompose file referenceservices referenceClaude Code common workflows

实际试用本文配置后,Masa 的测试项目可以通过 make up 同时启动 app、Postgres、Redis 和 worker,healthcheck 也减少了应用早于数据库启动的竞态问题。剩下最容易踩的坑是旧 named volume:它可能让 migration 看起来坏了,或者错误地看起来已经修好。结论是,Compose 是本地开发的强力足场,但生产环境仍然需要单独做安全、运维、恢复和成本审查。

#Claude Code #Docker #Docker Compose #本地开发 #PostgreSQL #Redis
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。