执行 docker compose up 时,看到某个变量未设置,或者配置里本该出现的镜像标签、端口变成空值,先别急着改容器内部的环境。Compose文件插值发生在创建容器之前,来源是运行Compose的Shell或指定的环境文件。
最容易混淆的两件事是 .env 用来填充Compose文件,以及 env_file 给容器注入变量。两者作用不同,先弄清谁在读取哪份文件。

先确认报错发生在配置解析还是容器运行
进入项目目录,仅检查配置能否解析,不启动任何容器:
cd /srv/myapp
docker compose config --quiet
如果必填变量缺失,命令会直接报告变量名;若只有警告,Compose可能把未定义变量替换为空字符串。配置检查通过不代表应用一定能启动,但能先排除插值阶段的错误。 不要在工单或公开日志里粘贴完整的 docker compose config 输出,渲染结果可能包含密码。
检查Compose究竟从哪里读取.env
Docker文档规定变量来源优先考虑运行命令时的Shell环境;显式 --env-file 可指定文件;未指定时才按项目目录规则查找 .env。先确认工作目录和文件名:
pwd
ls -la compose.yaml .env
docker compose --env-file /srv/myapp/.env config --quiet
用 -f 指定其他目录的Compose文件、在定时任务中切换了工作目录,或文件名写成 .env.txt,都可能让实际读取位置不同。不要把 .env 文件存在,等同于这次命令一定加载了它。
区分Shell变量和.env变量的优先级
同名变量同时存在于Shell和环境文件时,Shell的值优先。只查询是否存在,避免打印生产密钥:
if [ "${APP_PORT+x}" ]; then echo 'APP_PORT已在Shell中设置'; fi
docker compose config --environment
第二条命令会列出插值使用的变量和值,只适合在可信的本地终端检查,不要上传输出或让CI直接记录。确认旧Shell值后,可在当前会话中按需 unset APP_PORT,再用 config --quiet 验证。
用必填语法避免静默产生空配置
Compose支持带错误提示的必填变量写法。下面的例子要求镜像标签既已设置又非空:
services:
web:
image: "example/web:${IMAGE_TAG:?请设置IMAGE_TAG}"
ports:
- "${WEB_PORT:-8080}:80"
${IMAGE_TAG:?说明} 会在缺失或为空时停止解析;${WEB_PORT:-8080} 则在缺失或为空时使用默认值。密码、镜像版本和对外监听地址不要随手设成一个看似方便的默认值。 改完只运行 docker compose config --quiet,确认无误后再执行部署。
不要把env_file误当作Compose插值来源
services.web.env_file 是把文件里的变量传进容器环境,不能直接保证 image: "example/web:${IMAGE_TAG}" 在Compose解析时拿到值。需要插值时,应把变量放到Shell、默认 .env 或命令行 --env-file 指定的文件中。
容器是否真的收到应用环境变量,则在成功启动后检查特定的非敏感变量。切勿用 docker inspect 的完整输出公开排障,里面可能包含容器环境中的凭据。
在脚本和不同机房环境中稳定复现
运维脚本应明确Compose文件、环境文件和项目目录,而不是依赖脚本被谁从哪个目录调用:
docker compose --project-directory /srv/myapp \
--env-file /srv/myapp/.env \
-f /srv/myapp/compose.yaml config --quiet
需要在隔离VPS上复现部署差异,可分别用 萤光云 和 LightNode 建立测试环境。测试时只使用替代密钥,不要把生产 .env 复制到临时服务器。
修正后怎样确认真正生效
先执行 config --quiet,再确认镜像版本及应用监听端口是预期值,最后才执行 docker compose up -d。运行后检查 docker compose ps 和相关服务日志,确保没有把空值转移成应用内部错误。
验收标准是从部署脚本实际使用的目录和参数重新执行,变量不再报警,容器接收到预期的非敏感配置。 单次手工切换目录成功,还不能证明自动化任务也会成功。
FAQ
为什么手动执行正常,计划任务却提示变量没设置? 计划任务可能使用不同工作目录和Shell环境,应显式指定 --project-directory、-f 与 --env-file。
为什么改了env_file,镜像标签仍为空? env_file 负责传入容器,镜像标签是在容器创建前插值,需核对Compose命令本身使用的变量来源。
温馨提示
先检查变量来源和解析结果,再重启容器。 排障命令可能显示密钥,应把日志与截图当成敏感信息处理。


