首页/云/Docker 容器速查/ENV 与 RUN export 的区别
镜像与构建107 条

ENV 与 RUN export 的区别

RUN 里的 export 只是当条命令的 shell 变量,下一条指令就消失;需要跨层、跨运行期的持久变量使用 ENV。

Docker 容器速查云更新于 2026-10-13

ENV 与 export 的区别

两者看起来都在设置变量,但生命周期完全不同。RUN 里写 export 设置的是那一条命令所在 shell 会话的变量,命令结束就消失,下一条 RUN 是新进程,读不到;ENV 写入镜像配置,后续所有构建步骤与容器运行时都能读到。搞混这两者,是「构建脚本里明明设置了,下一条指令却读到空值」这类问题的根因。

基本信息

RUN export仅当前 shell 会话有效,随命令结束消失
ENV写入镜像配置,构建后续步骤与运行时均生效
查看方式docker image inspect -f '{{json .Config.Env}}' 镜像
ARG 对比ARG 只在构建期可用,不进镜像配置
运行时覆盖docker run -e KEY=值 覆盖镜像内 ENV
多阶段影响ENV 只在声明的阶段内生效,跨阶段需显式传递

典型使用场景

  • 构建期临时变量(版本号、下载地址)用 shell 变量即可,不必写进镜像
  • 应用默认配置(时区、语言、运行环境名)用 ENV,让运行时自动可用
  • 排查容器读不到变量:先看镜像配置里有没有这个键
  • 区分构建参数与运行时配置:构建参数不应残留在最终镜像里
  • 多阶段构建中把上游阶段的路径或版本传递给下游阶段

三种写法的差别

三种写法的差别
# 一、shell 变量:只在本次 RUN 内有效
RUN export FOO=bar && echo "$FOO"     # 能打印 bar
RUN echo "$FOO"                       # 打印空值,变量已随上条命令消失

# 二、ENV:写入镜像配置,后续步骤与运行时都能读到
ENV APP_ENV=production \
    TZ=Asia/Shanghai
RUN echo "$APP_ENV"                   # 能读到

# 三、ARG:只在构建期使用,不进入镜像配置
ARG APP_VERSION=dev
RUN echo "building ${APP_VERSION}"     # 能读到,但运行容器时不存在这个变量

核对与覆盖

核对与覆盖
# 查看镜像内置的环境变量
docker image inspect -f '{{json .Config.Env}}' app/web:1.0

# 运行时覆盖(仅本次容器生效)
docker run -d -e APP_ENV=staging --name api app/web:1.0

# 确认容器内实际取值
docker exec api env | grep -E 'APP_ENV|TZ'

# 多阶段构建中把变量显式传给下游阶段
# FROM build AS builder ... ENV OUT=/out
# FROM runtime ... COPY --from=builder $OUT/app /app

变量类型对照

写法构建期可见运行期可见写入镜像配置
RUN export仅本条命令不可见否
ENV后续步骤可见是
ARG本阶段内不可见否
docker run -e无关仅该容器否
基础镜像 ENV后续步骤可见是(继承)
构建阶段用 ENV 设置的变量会留在最终镜像里,多余的调试变量可能影响应用的配置优先级,交付前应清理只用于构建的项。
需要变量展开与默认值时,shell 形式或显式套一层 shell 都可以;exec 形式(JSON 数组)不展开变量,参数会原样传入。

易错点

  • 把 export 当持久化设置是常见误区,下一条指令读不到时先检查这条
  • 构建阶段用 ENV 留下的变量会转成容器默认配置,可能覆盖应用自身默认值导致行为变化
  • 把构建期参数用 ENV 写进镜像,敏感值随镜像一起分发出去
  • 多阶段构建里以为上游的 ENV 会自动传递到下游阶段,实际需要显式声明或通过文件传递

数据来源与参考

  • Docker 官方文档:Dockerfile ENV(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌