在Docker中,stage和step有什么区别?
在Docker构建过程中,stage
(阶段)和step
(步骤)是两个不同的概念,分别对应构建过程的不同层级,核心区别在于范围和作用:
1. step
(步骤):构建过程的最小单元
step
指的是 Dockerfile 中单个指令的执行过程,是构建镜像的最小操作单元。
例如 FROM
、RUN
、COPY
、WORKDIR
等每一条指令,在构建时都会被视为一个独立的 step
。
-
特点:
- 每个
step
都会基于上一个step
的结果创建一个新的镜像层(layer),Docker 通过分层缓存机制加速构建(若指令未变,可复用缓存层)。 - 所有
step
按顺序执行,共同构成一个完整的构建流程。
- 每个
-
示例:
以下 Dockerfile 包含 4 个step
:FROM ubuntu:22.04 # step 1:指定基础镜像 WORKDIR /app # step 2:设置工作目录 COPY . . # step 3:复制文件 RUN apt-get install -y nginx # step 4:执行安装命令
2. stage
(阶段):由多个 step
组成的逻辑单元
stage
是 多阶段构建(multi-stage build) 中的概念,指一组相关的 step
组成的逻辑单元,用于实现“分阶段构建、精简最终镜像”的目标。
每个 stage
以 FROM
指令开始,可通过 AS <名称>
命名,便于后续阶段引用。
-
特点:
- 一个 Dockerfile 可以包含多个
stage
,每个stage
独立构建,拥有自己的基础镜像和step
。 - 最终镜像只保留最后一个(或指定的)
stage
的内容,之前的stage
可用于编译、构建等中间过程(如编译代码的工具链不需要出现在最终镜像中)。 - 可通过
COPY --from=<阶段名/序号>
从其他stage
复制文件到当前stage
,实现“只保留必要产物”的目的。
- 一个 Dockerfile 可以包含多个
-
示例:
以下 Dockerfile 包含 2 个stage
,每个stage
包含多个step
:# 第 1 个 stage(命名为 builder):编译代码 FROM golang:1.20 AS builder # stage 1 开始,命名为 builder WORKDIR /app # stage 1 的 step 1 COPY main.go . # stage 1 的 step 2 RUN go build -o myapp main.go # stage 1 的 step 3(编译出可执行文件) # 第 2 个 stage:生成最终镜像 FROM alpine:latest # stage 2 开始(默认是最终镜像) WORKDIR /app # stage 2 的 step 1 COPY --from=builder /app/myapp . # stage 2 的 step 2(从 builder 阶段复制产物) CMD ["./myapp"] # stage 2 的 step 3
上述构建中,
builder
阶段用于编译 Go 代码(包含 3 个step
),最终镜像仅保留第 2 个阶段的内容(包含 3 个step
),大幅减小了镜像体积。
核心区别总结
维度 | step (步骤) |
stage (阶段) |
---|---|---|
定义 | 单个 Dockerfile 指令的执行过程 | 一组相关 step 组成的逻辑单元(多阶段构建中) |
范围 | 最小执行单元,对应一个镜像层 | 包含多个 step ,是构建流程的“子流程” |
作用 | 完成具体操作(如复制文件、执行命令) | 实现特定目标(如编译、打包、生成最终镜像) |
多阶段构建中 | 属于某个 stage 的一部分 |
可独立命名和引用,用于分离中间过程和最终产物 |
最终镜像影响 | 所有 step 的层会累积到所在 stage 中 |
仅最后一个 stage 的内容保留在最终镜像中 |
简言之:step
是构建的“原子操作”,stage
是由多个 step
组成的“功能模块”,多阶段构建通过 stage
分离构建过程和最终产物,从而优化镜像。