arg仅在当前构建阶段有效,多阶段中需每阶段显式声明同名arg才能使用;可通过--build-arg动态传参,结合条件指令实现开发、测试、生产等环境差异化构建。
多阶段构建本身不直接控制“运行时环境”,但可以通过 arg 在构建阶段注入参数,影响各阶段的行为(比如选择基础镜像、启用调试功能、生成不同配置的产物),从而让最终镜像适配开发、测试或生产等环境。
用 ARG 定义环境变量并在各阶段生效
ARG 只在构建阶段有效,且作用域限于当前阶段。因此,若需在多个阶段使用同一参数(如 ENVIRONMENT=prod),必须在每个阶段开头显式声明:
- 在第一阶段(构建)中定义 ARG,用于控制编译行为(例如是否开启调试符号、是否压缩资源)
- 在第二阶段(运行)中重新声明同名 ARG,用于决定是否复制调试工具、加载哪套配置文件
示例:
ARG ENVIRONMENT=production
FROM golang:1.21 AS builder
ARG ENVIRONMENT
WORKDIR /app
COPY . .
RUN if [ "$ENVIRONMENT" = "development" ]; then \
go build -gcflags="all=-N -l" -o server .; \
else \
CGO_ENABLED=0 GOOS=linux go build -a -o server .; \
fi
<p>ARG ENVIRONMENT
FROM alpine:latest AS runtime
ARG ENVIRONMENT
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .</p><h1>根据环境决定是否添加调试工具</h1><p>RUN if [ "$ENVIRONMENT" = "development" ]; then \
apk add --no-cache strace curl; \
fi
CMD ["./server"]
</p>
结合 --build-arg 实现构建时动态切换
构建命令中通过 --build-arg 覆盖默认值,无需修改 Dockerfile 即可产出不同用途的镜像:
-
docker build --build-arg ENVIRONMENT=development -t myapp:dev .→ 带调试工具和未优化二进制 -
docker build --build-arg ENVIRONMENT=production -t myapp:prod .→ 精简、静态链接、无额外工具
CI/CD 中可基于分支自动传参:main 分支用 production,feature 分支用 staging,本地开发用 development。
用 target 控制构建范围,配合 ARG 提升调试效率
多阶段构建支持 --target 指定只构建到某阶段。这对环境参数调试很实用:
-
docker build --target builder --build-arg ENVIRONMENT=development -t myapp:builder-test .→ 快速验证构建逻辑是否按预期执行 - 再用
COPY --from=myapp:builder-test测试运行阶段行为,避免反复全量构建
注意:target 阶段内仍需声明所需 ARG,否则无法读取传入值。
避免常见误区:ARG 不会自动跨阶段传递
很多人误以为在第一个 FROM 前定义一次 ARG 就能全局生效,这是错误的。Docker 规则明确:
- 每个阶段是独立构建上下文,ARG 必须在该阶段
FROM后、首次使用前声明 - 即使阶段名相同(如都叫
builder),也不共享 ARG 值 - 未声明 ARG 而直接引用(如
RUN echo $ENVIRONMENT)会输出空字符串,不易察觉
建议在每个阶段开头统一加一行 ARG ENVIRONMENT,保持可读性和健壮性。











