← 返回资讯
林远舟
技术编辑
已审核

Docker Compose 生产环境避坑指南:我不说你永远不知道的 7 个坑

Docker Compose 是开发利器,但直接搬到生产环境会炸。

Docker Compose 生产环境避坑指南:我不说你永远不知道的 7 个坑

Docker Compose 生产环境避坑指南:我不说你永远不知道的 7 个坑

Docker Compose 是开发利器,但直接搬到生产环境会炸。

我亲眼见过一个团队把 docker-compose.yml 从本地直接推到服务器,结果第二天早上发现数据库被删了。原因是容器重启时 volume 没挂对。

下面是我在生产环境踩过的 7 个坑。

坑 1:restart 策略不当

YAML
# 错误示范 - 永远不会重启
services:
  api:
    image: myapp:latest
    # 没有 restart 策略!
    
# 正确配置
services:
  api:
    image: myapp:latest
    restart: unless-stopped
    # always: 无论什么原因退出都重启
    # unless-stopped: 手动停止才不重启
    # on-failure: 仅非零退出码时重启

坑 2:数据库密码硬编码

YAML
# 危险!
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: mypassword123  # 硬编码密码

# 安全做法
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

坑 3:资源限制缺失

一个容器内存泄漏就能拖垮整台机器:

YAML
services:
  api:
    image: myapp:latest
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

坑 4:健康检查缺失

YAML
services:
  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s  # 给数据库启动留时间
  
  api:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy  # 等数据库健康后才启动
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

坑 5:日志无限增长

YAML
services:
  api:
    image: myapp:latest
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

坑 6:网络配置不当

YAML
# 好的网络隔离
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 不暴露到外网

services:
  nginx:
    networks:
      - frontend
  api:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend  # 数据库只在内网可访问

坑 7:数据卷不持久化

YAML
services:
  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
      # 不是 ./data:/var/lib/postgresql/data(相对路径坑)

volumes:
  postgres_data:
    driver: local
    # 显式命名 volume,容器删除后数据仍在

生产级 docker-compose.yml 模板

YAML
version: '3.8'

x-common: &common
  restart: unless-stopped
  logging:
    driver: "json-file"
    options:
      max-size: "10m"
      max-file: "3"

services:
  nginx:
    <<: *common
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - certbot_data:/etc/letsencrypt
    networks:
      - frontend
    healthcheck:
      test: ["CMD", "nginx", "-t"]
      interval: 30s
      timeout: 10s
      retries: 3

  api:
    <<: *common
    image: myapp:${APP_VERSION:-latest}
    environment:
      DATABASE_URL: postgresql://postgres:${DB_PASSWORD}@db:5432/myapp
    env_file:
      - .env.production
    deploy:
      resources:
        limits:
          memory: 512M
    networks:
      - frontend
      - backend
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  db:
    <<: *common
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  postgres_data:
  certbot_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

记住:开发环境用 Compose 是方便,生产环境用 Compose 是责任。

438
6269 阅读
3 评论
分享
链接已复制
编辑说明

本文由 MakeSense 编辑团队撰写并审核。文中引用的数据和观点均经过交叉验证,如有疏漏欢迎在评论区指正。最后更新:2026年07月12日 11:21

林远舟

技术编辑

全栈工程师出身,做过 5 年技术社区运营。对 AI 编程工具、开发者生态有深入研究,喜欢用实测数据说话。

读者评论 3

运营小陈 1周前
转发到团队群了,大家都觉得有参考价值。
回复 点赞 (4)
数据分析师 昨天
数据引用很扎实,建议补充一下近三个月的最新数据。
回复 点赞 (9)
产品经理阿杰 4天前
从产品角度看,这个方向确实有机会,但商业化路径还需要验证。
回复 点赞 (15)