第03章:AI帮我写了docker-compose,本地能跑,服务器为什么崩?

第03章:AI帮我写了docker-compose,本地能跑,服务器为什么崩?

“在我的机器上是好的”——这是容器化本来应该解决的问题,但很多人用了docker-compose之后还是碰到了它。
本地能跑,到了服务器就出错。AI写的docker-compose,有哪些只在本地有效的假设?

这一章告诉你:AI生成的docker-compose.yml在生产环境的常见失效点,以及如何写出真正跨环境可用的配置。


ℹ️ 版本说明:本章基于 Docker Compose v2.xdocker 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_oncondition: service_healthy + 数据库的 healthcheck

⚠️ 坑3:没有数据卷(Volume),容器重启数据消失

AI生成的 PostgreSQL 配置没有挂载数据卷,数据存在容器内部。
docker compose down 后,数据库数据全部删除。
在生产环境,这等于每次重部署都清空数据库。

⚠️ 坑4:资源没有限制(内存耗尽导致整机崩溃)

没有 mem_limitdeploy.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 不等于"等数据库就绪",只是"等数据库容器启动"。
必须配合数据库的 healthcheckcondition: service_healthy 才能真正保证启动顺序。
同时,所有密码用 .env 文件,永远不要硬编码在 docker-compose.yml 里。


→ 第04章:AI写的容器配置,数据能持久化吗?