> 关键工具:Claude Code + Docker Compose
> 技术栈阶:高阶——多服务编排与持久化
> 完整演示:构思 → 创建项目 → 提示词编写 → AI 制作 → 项目检验 → 落地
> 预计耗时:跑通本地编排约 2~3 小时;部署到服务器再 1~2 小时
这一篇怎么读
目标:把一个全栈应用(前端 + 后端 + Redis + PostgreSQL)容器化,一键拉起、正确互联、数据持久。本篇演示"启动顺序依赖"和"数据卷持久化"这两个 AI 默认不会替你想周全的 30%,并真正部署到一台服务器。
阶段一 · 构思:先列清服务和它们的依赖关系
- 场景:全栈 AI 应用本地能跑,但要让它在任何机器上一键拉起、稳定运行。
- 核心:四个服务——frontend、backend(API)、redis、postgres,要正确互联、数据不丢。
- 两个必须提前防的 30%(构思阶段就锁定):启动顺序(后端不能在数据库就绪前启)、数据卷持久化权限(容器重启数据不能丢)。
- 成功标准:在一台干净机器上 clone +
docker compose up一次成功,重启数据还在。
阶段二 · 创建项目:装 Docker、规划 compose 骨架
- 确认 Docker 环境:
docker --version && docker compose version # 确认本机有 Docker 与 compose
- 进项目、启动 Agent:
cd <fullstack-app> && claude
- 准备
.env(密钥不进 compose)和.dockerignore:
# .env(compose 引用,不硬编码密钥)
POSTGRES_PASSWORD=...
# .dockerignore:排除 node_modules、.git、.env
为什么先理服务依赖
容器编排的本质是"让有依赖关系的多个服务正确地协同起来"。动手前先在脑子里画清"谁连谁、谁依赖谁",提示词才写得准。
阶段三 · 具体提示词编写:把两个 30% 写进工单
起手提示词(在项目根目录启动 claude)
把这个全栈应用容器化,用 Docker Compose 编排四个服务:
frontend(Vite 静态前端)、backend(Node API,端口3000)、postgres、redis。
分步来,先给我整体方案再写文件。
【要求】
- frontend、backend 各写多阶段构建 Dockerfile(产物精简,不塞源码/devDeps)。
- 四服务能用服务名互访(backend 连 host=postgres、host=redis)。
- 【关键-启动顺序】backend 必须等 postgres 真正"可接受连接"后再启,
不能只用 depends_on。用 postgres 的 healthcheck +
depends_on 的 condition: service_healthy。
- 【关键-持久化】postgres 数据用具名 volume 持久化,重启/重建不丢。
- 密钥走 .env,不硬编码进 compose。
先把方案和依赖关系讲给我,再生成文件。阶段四 · AI 制作:看产出(关键片段)与第一颗定时炸弹
AI 给出 compose,四服务用 depends_on 串起,docker compose up 也都起来了。关键片段:
# docker-compose.yml(AI 初版,关键片段——藏着炸弹)
services:
backend:
build: ./backend
depends_on: [postgres, redis] # ⚠️ 只保证"启动",不保证"就绪"
environment:
DB_HOST: postgres
postgres:
image: postgres:16
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
反复重启几次,backend 偶尔崩溃——它启动太快,postgres 还没准备好接受连接。depends_on 只保证容器启动先后,不保证服务就绪。
阶段五 · 项目检验(上):填掉就绪、持久化、安全三个坑
5.1 坑①:启动顺序——healthcheck + 应用重试双保险
修复启动顺序提示词
backend 偶发连不上 postgres(depends_on 只保证启动不保证就绪)。请改:
- 给 postgres 加 healthcheck,用 pg_isready 检测真正可连。
- backend 的 depends_on 用 condition: service_healthy。
- backend 自己也加连接重试(失败退避重试几次),防瞬时抖动。# 修复后(关键片段)
postgres:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
retries: 5
backend:
depends_on:
postgres: { condition: service_healthy } # 等健康才启动
"健康检查 + 应用重试"双层防护,是生产级编排的标配。
5.2 坑②:数据持久化与卷权限
测"重建容器数据不丢",发现 AI 初版把数据放容器内部,down 后全没:
持久化修复提示词
postgres 数据没持久化。用具名 volume(pgdata)挂到
/var/lib/postgresql/data。验证:写数据→down(不带-v)→up,数据应还在;
down -v 才清空。并确认挂载目录权限正常,postgres 用户能写。果然又踩权限坑:挂载目录属主和容器内 postgres 用户对不上,数据库启动报权限错误——这是"数据卷持久化权限"的典型表现。
5.3 坑③:镜像瘦身 + 非 root
跑通后 backend 镜像 1.2GB(把源码和 devDeps 全打进去了):
优化提示词
backend 镜像太大。多阶段构建:构建阶段装全部依赖+编译,运行阶段只复制
产物+生产依赖;基础镜像用 node:20-slim;不要用 root 跑应用,建非 root 用户。"不要用 root 跑应用"是容器安全基本功——被攻破后能大幅限制破坏范围,而 AI 默认常用 root。
阶段五 · 项目检验(下):验收清单
| 检验项 | 操作 | 期望 |
|---|---|---|
| 启动顺序 | 反复 up/restart 多次 | backend 不再因连不上 DB 崩 |
| 持久化 | 写数据→down(不带-v)→up | 数据还在;down -v 才清空 |
| 卷权限 | 看 postgres 启动日志 | 无权限报错,能写入 |
| 可移植 | 干净机器上 clone + up | 一次成功 |
| 安全 | 查运行用户、镜像内容 | 非 root 运行,密钥不在镜像里 |
阶段六 · 落地:部署到真实服务器并长期运行
本地编排通了,最后落地到一台云服务器(VPS)上真正对外服务。
- 服务器装 Docker,把代码拉上去:
ssh user@your-server
git clone <repo> && cd <repo>
cp .env.example .env && vim .env # 在服务器上填生产密钥
- 后台启动并设开机自启:
docker compose up -d # -d 后台运行
# compose 里给各服务设 restart: unless-stopped,机器重启后自动拉起
- 前置一个反向代理 + HTTPS(如 Caddy / Nginx),把 80/443 流量转给 frontend/backend,并自动签发证书。
- 冷启动验证:从外网用域名完整访问一遍;重启服务器,确认
restart策略让服务自动恢复、数据卷数据还在。
落地最常见翻车
概念版那句话在这里应验:"本地能跑、线上不行"九成是顺序/权限/环境变量。上线后务必复测:服务器重启后服务能否自愈、数据卷是否真的持久、生产 .env 是否配全。
30% 复盘:人类到底守住了什么
AI 能很快生成 Dockerfile 和 compose 骨架(70%)。让这套编排"在生产里真的稳"的 30%,是人类对系统机制的理解:
| 30% 工程点 | 人类做了什么 | 不做会怎样 |
|---|---|---|
| 启动就绪 | healthcheck + service_healthy + 应用重试 | backend 偶发连不上 DB 崩 |
| 数据持久化 | 具名 volume + 验证 down/up 不丢 | 容器一删数据全没 |
| 卷权限 | 对齐属主、修挂载权限 | postgres 因权限错起不来 |
| 镜像与安全 | 多阶段瘦身 + 非 root | 镜像臃肿、被攻破风险大 |
核心教训:Docker 让"打包环境"变简单了,但"编排有依赖的多服务"和"管理持久化数据"依然是需要工程经验的硬骨头。 AI 能写配置骨架,但"为什么 backend 偶发崩、为什么 DB 起不来"这类排障,靠的是你对就绪探测、卷权限的真正理解。
可复用心法与提示词模板
带得走的三条
- depends_on 不等于就绪:用 healthcheck + condition: service_healthy,应用层再加重试。
- 数据必须具名 volume 持久化:并亲自验证 down/up 不丢、注意挂载权限。
- 镜像多阶段 + 非 root:瘦身和安全是 AI 默认偷懒、要人补的地方。
通用"多服务容器编排"提示词骨架:
用 Docker Compose 编排 <服务列表>。先讲方案与依赖关系,再写文件。
1. 各服务多阶段 Dockerfile,运行阶段只留产物+生产依赖,非 root 运行。
2. 服务间用服务名互访;密钥走 .env,不硬编码。
3. 【就绪】有依赖的服务用被依赖方 healthcheck + condition: service_healthy,
应用层再加连接重试。
4. 【持久化】有状态服务用具名 volume,给我验证 down/up 不丢数据的步骤。
5. 加 .dockerignore;给"干净环境一键启动"的验证步骤写进 README。