arg仅在构建时生效,env则固化进镜像供运行时使用;需构建传参且运行时访问时,先用arg声明再通过env ${var}中转;敏感信息严禁写入二者,应使用--secret或文件挂载。

ENV 和 ARG 都能在 Dockerfile 里设变量,但它们根本不是一回事——一个管“运行时”,一个只活在“构建时”。用错地方,轻则配置不生效,重则泄露敏感信息或构建失败。
ARG:只在构建过程中起作用的临时参数
ARG 定义的变量仅存在于 docker build 执行期间,镜像生成后就彻底消失,容器里完全看不到。它适合传入版本号、构建路径、临时密钥(虽不推荐存密钥,但至少不会留在镜像里)这类只用一次的信息。
- 语法:
ARG APP_VERSION=1.0.0,可带默认值;没默认值又没用--build-arg指定,构建直接报错 - 生效范围:从声明位置开始,到下一个
FROM(多阶段构建中)或构建结束为止 - 传参方式:必须用
docker build --build-arg APP_VERSION=2.2.0 .显式传入 - 注意:不能直接在
CMD或ENTRYPOINT中被应用读取,因为容器启动时它已不存在
ENV:固化进镜像、运行时持续可用的环境变量
ENV 设置的变量会写入镜像层,容器一启动就自动加载,所有进程都能通过 os.Getenv() 或 printenv 读到。适合配置端口、环境模式、日志路径等应用长期依赖的设定。
- 语法:
ENV NODE_ENV=production PORT=8080,支持多变量连续定义 - 生效范围:全局,构建阶段和容器运行时都有效,且子进程自动继承
- 覆盖方式:构建时无法修改;运行时可通过
docker run -e NODE_ENV=development覆盖 - 注意:值会保留在镜像中,
docker history或导出镜像后可能被看到,不适合放密码、token 等
怎么把 ARG 的值传给 ENV?让构建参数“活”到运行时
常见需求是:构建时动态指定某个值(比如数据库地址),又希望容器启动后还能用。这时不能直接用 ARG,而要“中转”给 ENV:
- 写法示例:
ARG DB_HOST<br>ENV DB_HOST=${DB_HOST} - 这样,构建时用
--build-arg DB_HOST=prod-db.example.com传入,该值就会固化为镜像的环境变量 - 关键点:ARG 必须在 ENV 前声明,且 ENV 引用时要用
${VAR}语法,不能漏掉花括号 - 安全提醒:这种中转会把原本只存在于构建阶段的值,永久写入镜像——如果传的是密钥,依然不安全
选哪个?看变量要“活多久”
判断标准很简单:
- 只在
RUN命令里下载、编译、打标签用?→ 用 ARG - 应用启动后要读取(比如连接数据库、切换开发/生产模式)?→ 用 ENV
- 既要构建时灵活传参,又要运行时能访问?→ 先 ARG,再赋值给 ENV
- 涉及密码、token、私钥?→ 别硬塞进 ARG 或 ENV,改用
docker run --secret或挂载文件











