Docker 环境变量传递进阶:优先级、覆盖与排错

Docker run 中 -e 覆盖镜像 ENV;Compose 的 environment 覆盖 env_file,再覆盖镜像 ENV,compose run -e 可覆盖该次配置;ARG 只存在于构建期。本文讲清覆盖关系、ARG 与 ENV 的分工及变量"不生效"的排查。

最佳实践
Docker 环境变量传递进阶:优先级、覆盖与排错封面

核心规则:同一个变量,运行期注入覆盖构建期设定——docker run 与Compose是两条独立启动路径。run中-e覆盖镜像ENV;Compose中environment覆盖env_file再覆盖镜像ENV,compose run -e可覆盖该次容器配置,不能把docker run排到Compose链上。ARG 则完全不同:只在构建期存在,运行期容器里根本看不到。

优先级一览(高→低)

# Dockerfile
ENV MODE=image-default
# compose
services:
  app:
    env_file: .env            # Compose中低于environment
    environment:
      - MODE=compose-value    # Compose中覆盖env_file
docker run -e MODE=runtime-value ...   # 独立docker run路径,覆盖镜像ENV,不修改Compose服务

ARG vs ENV 分工

ARG VERSION=latest          # 构建期参数,docker build --build-arg VERSION=1.2
FROM base:$VERSION
ARG VERSION
ENV APP_VERSION=$VERSION    # 想在容器里也能看到,显式转存 ENV
  • ARG:构建期有效,docker history 可见(别放密码),容器运行期不存在
  • ENV:构建期与运行期都有效,除非被 -e 覆盖

变量"不生效"排查顺序

# 1. 容器里实际的值
docker exec myapp printenv MY_VAR

# 2. 创建时注入的值
docker inspect myapp --format '{{.Config.Env}}'

# 3. compose 渲染后的最终配置
docker compose config | grep -A5 environment

三层应分开:inspect反映创建配置,exec默认沿用创建配置而非PID1后来export的变量,不能用exec推断主应用环境;Compose渲染结果则用于核对插值与容器注入。

compose 里两个 .env 的坑

  • docker compose 自动读项目根的 .env——用于yml 里的 ${VAR} 替换
  • 要注入容器内,可用 env_file 或 environment 显式传入;自动读取.env作插值并不等于全部注入

两个用途同名不同命,混用是最高频错误。

敏感变量的正确姿势

环境变量可被 docker inspect 读出,生产秘钥建议:秘钥文件挂载、编排层 Secret(K8s Secret/Swarm secret)、或启动时从密管系统拉取。

常见问题(FAQ)

Q:改了 .env 文件容器内怎么没变?
A:环境变量是创建期注入的,改文件后要 docker compose up -d 重建容器。

Q:数组型变量怎么传(如多个 host)?
A:环境变量只能是字符串,约定分隔符(逗号)由应用解析,或改用配置文件挂载。

Q:能在 ENTRYPOINT 里动态计算变量吗?
A:可以,entrypoint 脚本里 export 的变量对随后启动的主进程生效——这是运行期动态配置的常见模式。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台