Docker Compose 如何配置多环境环境变量文件区分开发生产

文章导读
在 Docker Compose 中区分开发和生产环境,最稳妥的做法是用多份 Compose 配置文件配合不同的 env_file,而不是依赖单一 .env 文件。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 参考来源
A A

在 Docker Compose 中区分开发和生产环境,最稳妥的做法是用多份 Compose 配置文件配合不同的 env_file,而不是依赖单一 .env 文件。

先说结论:多环境配置需要同时处理 Compose 解析层和容器运行层两套变量体系,用 -f 参数组合配置文件 + env_file 加载环境专属变量是最清晰的方案。

  • 适合:需要在开发、测试、生产之间切换配置的项目
  • 先准备:基础 compose.yaml + 环境专属 compose.dev.yaml/compose.prod.yaml + 对应 .env.dev/.env.prod 文件
  • 验收:用 docker compose config 确认变量注入正确,进容器用 env 命令验证运行时环境变量

命令速用版

开发环境启动:

docker compose -f compose.yaml -f compose.dev.yaml up -d

生产环境启动:

docker compose -f compose.yaml -f compose.prod.yaml up -d

指定环境文件启动:

ENVIRONMENT=prod docker compose `--env-file` .env.prod up -d

检查最终配置(不启动容器):

docker compose -f compose.yaml -f compose.prod.yaml config

为什么会这样

Docker Compose 有两套环境变量体系,很多人混淆导致配置不生效:

第一套是 Compose 解析层:项目根目录的 .env 文件用于替换 docker-compose.yml 中的 ${VAR} 占位符,比如镜像版本、端口号。这个变量在 Compose 解析文件时就确定了,不会进入容器内部。

第二套是容器运行层:服务定义中的 environment 或 env_file 提供的变量,最终会出现在容器内的 env 命令输出中,应用代码能读到这些值。

多环境配置的关键是让不同环境使用不同的 env_file,并配合外部变量控制 Compose 文件行为。单一 .env 文件无法同时满足这两层需求,所以需要文件分离策略。

分步处理

步骤 1:创建基础配置文件

在项目根目录创建 compose.yaml,定义所有环境共享的服务框架:

version: '3.8'
services:
  webapp:
    image: myapp:${APP_VERSION:-latest}
    ports:
      - "8080:8080"
    environment:
      - APP_ENV=${ENVIRONMENT}
    env_file:
      - .env.${ENVIRONMENT:-dev}
    depends_on:
      - db
  db:
    image: postgres:${POSTGRES_VERSION:-14}
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:

步骤 2:准备环境专属变量文件

创建 .env.dev 和 .env.prod:

# .env.dev
DB_URL=postgresql://dev-db:5432/myapp
DEBUG=true
LOG_LEVEL=debug

# .env.prod
DB_URL=postgresql://prod-db:5432/myapp
DEBUG=false
LOG_LEVEL=info

注意:这些文件不要提交到 Git,.env.example 作为模板提交。

步骤 3:创建环境专属 Compose 配置

开发环境 compose.dev.yaml:

version: '3.8'
services:
  webapp:
    build: .
    volumes:
      - ./src:/app/src
    environment:
      - DEBUG=true
  db:
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=devuser
      - POSTGRES_PASSWORD=devpass

生产环境 compose.prod.yaml:

version: '3.8'
services:
  webapp:
    image: myapp:1.2.0
    deploy:
      replicas: 3
  db:
    volumes:
      - /data/postgres:/var/lib/postgresql/data

步骤 4:启动时指定环境

开发环境:

Docker Compose 如何配置多环境环境变量文件区分开发生产
ENVIRONMENT=dev docker compose -f compose.yaml -f compose.dev.yaml up -d

生产环境:

ENVIRONMENT=prod docker compose -f compose.yaml -f compose.prod.yaml up -d

回滚提醒:如果配置有误,用 docker compose down 停止后修改,不要用 docker compose up `--force-recreate` 直接覆盖,先确认 config 输出正确。

怎么验证是否生效

检查 1:确认 Compose 解析的变量

docker compose -f compose.yaml -f compose.prod.yaml config

查看输出中 ${VAR} 是否已被替换为实际值。

检查 2:确认容器内环境变量

docker compose exec webapp env | grep APP_ENV
docker compose exec webapp env | grep DB_URL

应该能看到你在 env_file 或 environment 中定义的变量。

检查 3:确认服务行为

查看应用日志确认加载了正确的配置:

docker compose logs webapp | grep -i "environment\|config"

开发环境应该看到 DEBUG=true 相关日志,生产环境应该看不到调试信息。

常见坑

坑 1:.env 文件位置不对

Compose 默认只读取项目根目录的 .env 文件,子目录的 .env 不会自动加载。如果要用其他位置的文件,需要用 `--env-file` 参数显式指定。

坑 2:变量优先级混淆

环境变量优先级从高到低为:命令行参数 (-e) > compose 文件中 environment 字段 > env_file 指定的文件 > 系统环境变量 > .env 文件中的默认值。如果同一个变量在多处定义,高优先级的会覆盖低优先级的。

坑 3:数组配置合并规则

使用多个 Compose 文件时,数组类型配置(如 ports、volumes)会合并而非替换。如果生产环境想移除开发环境的端口暴露,需要在 prod 文件中显式定义,而不是期望它自动覆盖。

坑 4:敏感信息泄露

.env 文件包含密码等敏感信息,不要提交到 Git。建议创建 .env.example 作为模板提交,团队成员各自配置本地 .env 文件。CI/CD 流水线中通过注入环境变量而非文件来传递敏感信息。

坑 5:变量插值被禁用

某些场景下变量 ${VAR} 没有被替换,可能是使用了 `--no-interpolate` 选项,或者变量名拼写错误。用 docker compose config 命令可以查看最终解析后的配置,确认变量是否正确替换。

参考来源

  • Docker Compose 多环境配置管理——一套配置轻松适配开发、测试、生产环境
  • Docker Compose 环境变量配置详解 - 直角漫步 - 博客园
  • Docker Compose 多环境变量管理 (从入门到生产级落地)
  • Docker Compose 多环境变量管理:如何实现开发、测试、生产无缝切换
  • 附 004.Docker Compose 环境变量说明
  • 揭秘 docker-compose.yml 环境变量文件:如何优雅管理多环境配置