第03章:AI帮我写了docker-compose,本地能跑,服务器为什么崩?
第03章:AI帮我写了docker-compose,本地能跑,服务器为什么崩?
“在我的机器上是好的”——这是容器化本来应该解决的问题,但很多人用了docker-compose之后还是碰到了它。
本地能跑,到了服务器就出错。AI写的docker-compose,有哪些只在本地有效的假设?
这一章告诉你:AI生成的docker-compose.yml在生产环境的常见失效点,以及如何写出真正跨环境可用的配置。
ℹ️ 版本说明:本章基于 Docker Compose v2.x(
docker compose命令,不是旧的docker-compose)。
3.1 AI默认会生成什么
# AI 生成的 docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
depends_on:
- db
- redis
db:
image: postgres:16
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
redis:
image: redis:7
本地:一键启动,全部正常。服务器:数据丢失、密码明文、服务启动顺序错乱。
3.2 AI通常遗漏的4个坑
⚠️ 坑1:密码/密钥明文写在 docker-compose.yml 里
POSTGRES_PASSWORD: password 直接在配置文件里。
这个文件一旦提交到 Git,密码就永久暴露在代码历史里。
即使你后来删掉了这行,git log --all --full-history 仍然能找到。
正确做法:使用 .env 文件存放密钥(加入 .gitignore),在 compose 里用变量引用。
⚠️ 坑2:depends_on 只检查容器启动,不检查服务就绪
depends_on: db 只保证 db 容器启动了,但不保证 PostgreSQL 已经准备好接受连接。
应用启动时尝试连接数据库,数据库还在初始化中,连接失败,应用崩溃。
本地通常没问题(因为本地数据库早就在运行),服务器首次启动时必现。
正确做法:用 depends_on 的 condition: service_healthy + 数据库的 healthcheck。
⚠️ 坑3:没有数据卷(Volume),容器重启数据消失
AI生成的 PostgreSQL 配置没有挂载数据卷,数据存在容器内部。
docker compose down 后,数据库数据全部删除。
在生产环境,这等于每次重部署都清空数据库。
⚠️ 坑4:资源没有限制(内存耗尽导致整机崩溃)
没有 mem_limit 或 deploy.resources.limits,一个内存泄漏的应用会把服务器内存全部占满,
触发 OOM Killer,可能把 Redis、数据库等其他容器也杀掉,整个服务崩溃。
3.3 更好的提示词
提示词 P01:生成生产可用的 docker-compose.yml
使用时机:为你的多服务应用编写跨环境可用的 Compose 配置。
你是一个 Docker Compose v2 生产环境专家。
请为以下应用生成生产可用的 docker-compose.yml 和配套文件:
服务列表:
- 应用服务:[如:Python FastAPI / Node.js Express],端口 [8000]
- 数据库:[如:PostgreSQL 16 / MySQL 9.0]
- 缓存:[如:Redis 8.0]
- [其他服务,如 Nginx 反向代理]
生产要求:
1. 密钥管理:所有密码/密钥从 .env 文件读取(不能硬编码在 compose 文件)
- 给出 .env.example 模板
- 给出 .gitignore 中应排除的文件
2. 启动顺序:使用 healthcheck + depends_on condition: service_healthy
- 给出 PostgreSQL / Redis 的 healthcheck 配置
- 应用等待数据库真正就绪后才启动
3. 数据持久化:所有有状态服务(DB、Redis)使用命名卷(named volumes),
并说明 named volume 和 bind mount 的区别
4. 资源限制:为每个服务设置合理的 memory limit 和 cpu limit
[我的服务器规格:如 2核4GB],请分配各服务的资源配额
5. 重启策略:restart: unless-stopped(或者 always),说明区别
6. 网络隔离:应用服务不直接暴露数据库端口到宿主机
给出:docker-compose.yml + .env.example + 简短的启动说明
提示词 P02:分环境管理(本地/测试/生产)
使用时机:你需要管理多套环境的 Compose 配置。
你是一个 Docker Compose v2 多环境管理专家。
我需要为同一个应用管理三套环境:本地开发、测试(staging)、生产。
三套环境的主要差异:
本地开发:
- 代码实时热重载(volume mount 源代码)
- 不需要 HTTPS
- 使用 mock 数据或测试数据库
测试(staging):
- 使用真实的镜像(不是 build: .)
- 连接测试数据库
- 可能需要暴露调试端口
生产:
- 使用固定版本的已构建镜像(不 build)
- 严格的资源限制
- 不暴露调试端口
请给我 Docker Compose 多文件覆盖的方案:
- docker-compose.yml(基础配置)
- docker-compose.override.yml(本地开发,自动加载)
- docker-compose.staging.yml
- docker-compose.prod.yml
说明:
- 如何用 docker compose -f ... -f ... up 合并多个文件
- 环境变量如何在不同环境中管理(.env.local / .env.staging / .env.prod)
- 生产环境建议用 docker compose 还是迁移到 Kubernetes?(给出选择标准)
提示词 P03:docker-compose 排查启动问题
使用时机:compose 启动失败或服务反复重启,需要排查根因。
你是一个 Docker Compose v2 故障排查专家。
我的 docker compose up 遇到了以下问题:
[粘贴报错信息或 docker compose logs 输出]
请帮我排查,按以下步骤引导:
1. 根据错误信息,最可能的根因是什么?(给出2-3个候选)
2. 对应的排查命令:
- docker compose ps(服务状态)
- docker compose logs service_name(特定服务日志)
- docker compose exec service_name sh(进入容器排查)
3. 常见启动失败场景:
- 应用启动失败但不报错(反复重启):如何用 restart: "no" 保留现场
- 端口已被占用:如何找到并清理
- 数据库连接失败(在healthcheck之前连接):如何加启动等待
- 环境变量未注入:docker compose config 命令查看合并后的配置
4. 给出修复后的配置
额外:如何在每次 docker compose up 时确保数据库迁移(migrate)在应用启动之前完成?
3.4 docker-compose 验收清单
| 检查项 | 验证方法 | AI辅助 |
|---|---|---|
| 无明文密码(从.env读取) | grep -E "password|secret|key" docker-compose.yml 不应有硬编码值 |
用P01检查密钥管理 |
| depends_on 有 condition: service_healthy | 检查 depends_on 配置 | 用P01要求健康检查 |
| 有状态服务使用命名卷 | docker compose down && docker compose up,数据应保留 |
用P01检查volumes配置 |
| 有资源限制 | docker stats 显示各容器有内存上限 |
用P01配置资源限制 |
| 首次启动测试 | 全新机器,docker compose up,所有服务应正常启动(不需要预先运行状态) |
用P03排查首次启动问题 |
3.5 本章小结
如果你只记一件事:
depends_on: db 不等于"等数据库就绪",只是"等数据库容器启动"。
必须配合数据库的 healthcheck 和 condition: service_healthy 才能真正保证启动顺序。
同时,所有密码用 .env 文件,永远不要硬编码在 docker-compose.yml 里。
→ 第04章:AI写的容器配置,数据能持久化吗?