Docker Compose 环境变量详解:.env 和 env_file 有什么区别

举报
GGBondHere 发表于 2026/11/04 11:19:13 2026/11/04
【摘要】 介绍 Docker Compose 中 .env、environment 和 env_file 的区别,讲解变量插值、覆盖优先级、环境文件路径及配置生效方式,帮助排查容器环境变量读取失败的问题。

前言

使用 Docker Compose 部署应用时,经常会遇到需要配置端口、运行模式、数据库地址等参数的情况。

为了避免把所有参数直接写进 compose.yaml,很多项目都会提供一个 .env 文件。但实际使用时,有时明明已经在 .env 中配置了变量,容器启动后却没有读取到。

这其实涉及 Docker Compose 中两个不同的概念:配置文件的变量替换,以及容器运行时的环境变量。

下面结合具体示例,介绍 .env、env_file 和 environment 的区别。

一、.env 文件的作用

先看一个简单的 Compose 项目:

myapp/
├── compose.yaml
└── .env

假设 .env 中保存:

APP_PORT=8080
IMAGE_TAG=3.20

在 compose.yaml 中可以这样使用:

services:
  demo:
    image: "alpine:${IMAGE_TAG}"
    command: ["sleep", "3600"]

运行:

docker compose config

Compose 会解析配置文件中的变量,把 ${IMAGE_TAG} 替换成 .env 中的值。

最终镜像名称会被解析为:

alpine:3.20

需要注意,.env 的主要用途是为 Compose 提供变量替换所需的值。

把变量写进 .env,并不代表这些变量会自动出现在容器内部。

这也是不少环境变量问题的来源。

二、environment:明确传递容器环境变量

如果希望容器内部的程序能够读取某个变量,可以使用 environment。

例如:

services:
  demo:
    image: alpine:3.20
    command: ["sleep", "3600"]
    environment:
      APP_MODE: production
      LOG_LEVEL: debug

启动容器后,应用程序可以通过环境变量读取 APP_MODE 和 LOG_LEVEL。

environment 既支持上面的键值映射形式,也支持列表形式:

environment:
  - APP_MODE=production
  - LOG_LEVEL=debug

两种写法都可以使用。

如果不想把具体值写死,也可以结合 .env:

environment:
  APP_MODE: "${APP_MODE:-development}"

这里的 ${APP_MODE:-development} 表示:如果 APP_MODE 没有设置,或者值为空,就使用 development 作为默认值。

这种方式很适合需要在测试环境和生产环境之间切换的应用。

三、env_file:从文件批量传递变量

如果一个应用有很多环境变量,全部写在 compose.yaml 中可能会让配置变得很长。

这时可以使用 env_file。

例如项目结构:

myapp/
├── compose.yaml
└── app.env

app.env 内容:

APP_MODE=production
LOG_LEVEL=info
FEATURE_FLAG=on

Compose 配置:

services:
  demo:
    image: alpine:3.20
    command: ["sleep", "3600"]
    env_file:
      - ./app.env

这样 app.env 中的变量就会被传递到容器环境中。

与前面的 .env 自动加载机制不同,env_file 是在服务配置中明确指定一个文件,让其中的变量成为容器环境变量。

另外,env_file 支持指定多个文件:

env_file:
  - ./common.env
  - ./production.env

如果两个文件定义了同名变量,后面的文件通常会覆盖前面的值。

这里的相对路径以 Compose 配置文件所在目录为基准。

四、environment 和 env_file 同时配置怎么办?

这是一个比较常见的情况。

假设 app.env 中写着:

APP_MODE=development
LOG_LEVEL=info

而 compose.yaml 中又指定:

services:
  demo:
    image: alpine:3.20
    command: ["sleep", "3600"]
    env_file:
      - ./app.env
    environment:
      APP_MODE: production

最终容器中的 APP_MODE 会是 production,而 LOG_LEVEL 仍然是 info。

原因是对于同一个服务,environment 中明确声明的变量会覆盖 env_file 中的同名变量。

需要注意,环境变量还有其他来源,例如 Dockerfile 中的 ENV、运行命令中的 -e,以及 Compose 变量插值使用的终端环境变量。

因此不能只根据两个文件的内容就判断最终结果,需要结合实际启动方式。

五、如何检查实际生效的变量?

Docker Compose 提供了一个很有用的命令:

docker compose config

它会解析 Compose 文件、合并配置并替换变量,可以检查最终生成的服务配置。

如果只想查看 Compose 用于变量替换的环境,可以执行:

docker compose config --environment

需要注意,这里查看的是 Compose 插值使用的变量,不等于容器内部最终拥有的全部变量。

如果希望直接检查容器内部的环境,可以针对支持 Shell 的容器执行:

docker compose exec demo env

前提是 demo 服务已经运行,并且容器中存在 env 命令。

对于上面使用 Alpine 镜像的示例,也可以通过一次性容器测试:

docker compose run --rm demo env

这通常比反复修改配置、重启容器来猜测变量是否生效更直接。

但这些命令可能显示敏感信息,排查时不要随意将输出粘贴到公开论坛。

六、–env-file 和 env_file 不是一回事

这两个名字非常接近,但使用位置不同。

例如:

docker compose --env-file ./config/dev.env config

这里的 --env-file 是 Compose 命令行参数,主要用于指定变量替换时使用的环境文件。

而:

services:
  demo:
    env_file:
      - ./config/dev.env

这里的 env_file 是服务配置项,用于把文件中的变量传递到容器。

两者可以配合使用,但并不等价。

还有一个路径细节:

  • 命令行 --env-file 的相对路径通常基于执行命令的当前工作目录。
  • 服务中的 env_file 相对路径基于 Compose 文件的位置。

如果通过脚本或者管理面板执行 Compose,工作目录不同,就可能出现找不到环境文件的情况。

七、修改环境变量后为什么没有生效?

有时修改了 .env 或 app.env,然后执行:

docker compose restart

却发现容器里还是原来的值。

原因是 restart 主要用于重新启动现有容器,并不会因为环境文件发生变化就自动重新创建容器。

容器创建时的环境变量一般已经确定。

如果确实需要将新的环境配置应用到容器,可以考虑:

docker compose up -d --force-recreate demo

这个命令会重新创建指定服务的容器。

执行前需要确认业务的持久化目录、数据卷和重建影响。对于数据库等有状态服务,不建议在没有检查配置和备份的情况下直接重建。

八、环境变量不适合保存所有秘密信息

实际部署中,很多项目会把数据库密码、API Key 等内容放进环境文件。

这种方式虽然方便,但不代表数据已经被安全保护。

容器环境变量可能通过检查命令、进程信息或调试输出暴露,环境文件本身也可能被错误提交到 Git 仓库。

对于敏感凭据,可以根据实际环境考虑使用 Docker Compose secrets 或专门的密钥管理方案。

如果仍需使用本地环境文件,至少应该正确设置文件权限,并避免将包含真实凭据的文件提交到公开仓库。

总结

Docker Compose 中的环境变量主要涉及三个概念:

配置方式 主要用途
.env 为 Compose 配置提供变量替换值
environment 明确设置容器的环境变量
env_file 从文件批量设置容器环境变量

最重要的是区分 Compose 解析配置时使用的变量,以及容器创建后实际拥有的环境变量。

遇到变量不生效的问题时,建议先使用 docker compose config 检查配置解析结果,再查看容器内部的环境变量,最后确认容器是否已经根据新配置重新创建。

这样通常比反复重启容器更容易定位问题。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。