关键是分清变量生命周期:ARG仅用于构建时传参且不写入镜像,ENV固化进镜像供运行时使用;二者配合实现构建时传参、运行时生效,避免硬编码敏感信息。

用 Dockerfile 实现运行时动态配置注入,关键不是把配置“写死”,而是设计好变量的生命周期——哪些该在构建时决定,哪些必须留到容器启动时才生效。真正灵活的做法,是让镜像保持通用性,把环境相关参数剥离出去。
区分 ARG 和 ENV:别混用这两个指令
ARG 仅在 docker build 过程中有效,不会出现在最终镜像里;ENV 定义的变量则会固化进镜像,并在容器运行时可用。两者配合才能兼顾安全与灵活性:
- 用 ARG 接收构建参数(如 APP_ENV=prod),并在 Dockerfile 中显式转成 ENV
- 避免直接在 ENV 中写敏感值,比如 ENV DB_PASSWORD=xxx —— 这会留在镜像历史中,有泄露风险
- 若某变量只用于构建阶段(如选择镜像源、安装调试工具),就只用 ARG,不转 ENV
让镜像支持运行时覆盖:预留可被 -e 覆盖的 ENV
Dockerfile 中定义的 ENV 是默认值,它会被 docker run -e 显式传入的同名变量覆盖。这是实现“一次构建、多环境运行”的基础:
- 在 Dockerfile 中设合理默认值:ENV LOG_LEVEL=info、ENV API_TIMEOUT=5000
- 启动容器时用 -e 覆盖:docker run -e LOG_LEVEL=debug -e API_TIMEOUT=10000 myapp
- 注意变量名大小写和拼写一致性,Node.js 读 process.env.LOG_LEVEL,Java Spring Boot 默认映射为 log.level
批量管理配置:用 --build-arg-file + ARG/ENV 组合
当构建参数超过三四个,硬编码在命令行易出错。推荐用纯文本文件集中管理:
- 新建 build.env 文件,每行一个 KEY=VALUE(支持 # 注释和空行)
- Dockerfile 中仍需逐个声明 ARG KEY,再用 ENV KEY=${KEY} 转为运行时变量
- 构建命令:docker build --build-arg-file build.env -t myapp .
前端静态资源的请求地址怎么注入?别在构建时硬编码
很多前端项目在构建时就把后端地址打包进 JS,导致镜像无法跨环境复用。更合理的做法是:
- 构建阶段不注入 API 地址,保留占位符(如 window.API_BASE = '__API_BASE__')
- 运行时通过 nginx 的 envsubst 或 entrypoint 脚本,在容器启动时替换 HTML/JS 中的占位符
- 或改用运行时读取环境变量的方案:前端页面加载后调用 fetch('/api/env') 获取真实地址(需后端提供简单接口)


















