多阶段构建是一个新特性,需要 Docker 17.05 或更高版本的守护进程和客户端。对于那些努力优化 Dockerfiles 并使其易于阅读和维护的人来说,多阶段构建非常有用。
多阶段构建
多阶段构建是 Docker 17.05 的新增功能,它可以在一个 Dockerfile 中使用多个 FROM 语句,以创建多个 Stages(阶段)。每个阶段间独立(来源请求),可以通过 COPY --from 来获取其它阶段的文件
docker build
语法:
-f, --file string Name of the Dockerfile (default: "PATH/Dockerfile")
-t, --tag stringArray Name and optionally a tag (format: "name:tag")
--target string Set the target build stage to build
1. 只有最后一个 stage 才会被纳入 image 中
在下方 Dockerfile 中,我们创建了两个阶段。第一个阶段创建 s1.txt,第二个阶段创建 s2.txt,且第二个阶段会被加入最终 Image,其它不会。
# Stage 1
FROM alpine:3.8
WORKDIR /app
RUN echo "Hello, stage 1" > /app/s1.txt
# Stage 2
FROM alpine:3.8
WORKDIR /app
RUN echo "Hello, stage 2" > /app/s2.txt
结果:
zxm@zxm-pc:~/docker-test$ ls
Dockerfile_1
zxm@zxm-pc:~/docker-test$ docker build -f Dockerfile_1 -t demo:1.0 .
zxm@zxm-pc:~/docker-test$ docker run --rm --name demo_1 demo:1.0 ls /app
s2.txt
2. 阶段间复制文件
使用 COPY --from
指令,可复制前面阶段的文件,也可复制指定镜像的文件。
COPY --from=0 行只将前一阶段的构建工件复制到这个新阶段;FROM 指令的第一个整数从 0 开始,0代表第一阶段。
# Stage 1
FROM alpine:3.8
WORKDIR /app
RUN echo "Hello, stage 1" > /app/s1.txt
# Stage 2
FROM alpine:3.8
WORKDIR /app
COPY --from=0 /app/s1.txt /app
COPY --from=nginx:1.25-alpine /etc/nginx/nginx.conf /app
RUN echo "Hello, stage 2" > /app/s2.txt
结果:
zxm@zxm-pc:~/docker-test$ docker build -f Dockerfile_2 -t demo:2.0 .
zxm@zxm-pc:~/docker-test$ docker run --rm --name demo_2 demo:2.0 ls /app
nginx.conf
s1.txt
s2.txt
3. 阶段命名
使用在 FROM 后加上 as,进行阶段命名。这样就可以 COPY --from
指定阶段名
# Stage 1
FROM alpine:3.8 as build1
WORKDIR /app
RUN echo "Hello, stage 1" > /app/s1.txt
# Stage 2
FROM alpine:3.8 as build2
WORKDIR /app
COPY --from=build1 /app/s1.txt /app
RUN echo "Hello, stage 2" > /app/s2.txt
结果:
zxm@zxm-pc:~/docker-test$ docker build -f Dockerfile_3 -t demo:3.0 .
zxm@zxm-pc:~/docker-test$ docker run --rm --name demo_3 demo:3.0 ls /app
s1.txt
s2.txt
4. 仅构建其中的部分阶段
结果:
# Stage 1
FROM alpine:3.8 as build1
WORKDIR /app
RUN echo "Hello, stage 1" > /app/s1.txt
# Stage 2
FROM alpine:3.8 as build2
WORKDIR /app
COPY --from=build1 /app/s1.txt /app
RUN echo "Hello, stage 2" > /app/s2.txt
zxm@zxm-pc:~/docker-test$ docker build -f Dockerfile_4 --target build1 -t demo:4.0 .
zxm@zxm-pc:~/docker-test$ docker run --rm --name demo_4 demo:4.0 ls /app
s1.txt