Docker Compose 中可通过 .env 文件实现编译期变量替换,通过 env_file 实现运行时环境变量注入,二者结合可分离部署参数与应用配置,YAML 锚点还能简化多服务共用 env_file 的重复声明。

在 compose.yml(或 docker-compose.yml)中,不能直接定义“全局常量”,但可以通过几种标准、可靠的方式实现类似效果:让多个服务共享同一组变量值,并保持定义集中、易于维护。
以下是常用且推荐的实践方式:
使用 .env 文件定义默认变量
Docker Compose 会自动加载项目根目录下的 .env 文件(无需显式声明),其中的键值对可被 compose.yml 中的 ${VAR_NAME} 引用。
# .env APP_VERSION=1.2.3 DB_HOST=postgres REDIS_URL=redis://redis:6379
# compose.yml
services:
web:
image: myapp:${APP_VERSION}
environment:
- DB_HOST=${DB_HOST}
- REDIS_URL=${REDIS_URL}
api:
image: myapp:${APP_VERSION}
environment:
- DB_HOST=${DB_HOST}
- REDIS_URL=${REDIS_URL}✅ 优点:一处修改,全服务生效;支持本地覆盖(如不同环境用不同 .env.staging)
⚠️ 注意:.env 中的变量仅用于 compose.yml 模板替换,不会自动注入到容器内部环境变量中,除非你显式写进 environment 或 env_file。
使用 env_file 统一注入运行时环境变量
适合需要把相同环境变量批量传给多个服务的场景(比如密钥、配置项)。
# compose.yml
services:
web:
image: nginx
env_file:
- common.env # 所有服务共用的变量文件
worker:
image: python:3.11
env_file:
- common.env# common.env LOG_LEVEL=info API_TIMEOUT=30 FEATURE_FLAG_EXPERIMENTAL=true
✅ 优点:变量真实注入容器,各服务启动时可直接读取(如 os.getenv("LOG_LEVEL"))
⚠️ 注意:env_file 中的变量不会用于 compose.yml 自身的模板替换(比如不能写 image: myapp:${VERSION}),它只作用于容器运行时。
结合使用:.env + env_file 实现“编译期+运行时”双层常量
这是最灵活的组合:
-
.env控制镜像标签、端口、服务名等 部署参数 -
common.env提供容器内实际使用的 应用级配置
# compose.yml
services:
db:
image: postgres:${POSTGRES_VERSION:-15}
environment:
POSTGRES_DB: ${DB_NAME}
ports:
- "${DB_PORT}:5432"
app:
image: myapp:${APP_VERSION}
env_file:
- common.env
environment:
APP_ENV: ${ENVIRONMENT:-production}# .env APP_VERSION=2.0.0 POSTGRES_VERSION=15.3 DB_NAME=myapp_prod DB_PORT=5432 ENVIRONMENT=staging
# common.env CACHE_TTL=3600 SENTRY_DSN=https://xxx@sentry.io/123
这样既保证了构建/部署参数统一,又确保运行时配置清晰分离。
小技巧:避免重复写 env_file
如果所有服务都要加载同一组变量,可以利用 YAML 锚点(Anchor)简化写法:
x-common-env: &common-env
env_file:
- common.env
services:
web:
<<: *common-env
image: nginx
api:
<<: *common-env
image: golang:1.22这样新增服务时只需一行 <<: *common-env,不易遗漏。
不复杂但容易忽略的是:.env 是 Compose 解析时读取的,env_file 是容器启动时加载的——两者职责不同,搭配使用才真正高效。


















