Skip to content

Docker 多阶段构建

多阶段构建

多阶段构建是 Docker 17.05 版本引入的新特性,可以让我们在一个 Dockerfile 中定义多个构建阶段,每个阶段可以使用不同的基础镜像,这样可以减少镜像的大小。

dockerfile
FROM golang:alpine AS builder
RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld/
RUN go get -d -v github.com/go-sql-driver/mysql
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest AS prod
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/go/helloworld/app .
CMD ["./app"]

构建时,Docker 会按照 FROM 的顺序执行,每个阶段的镜像都可以使用 --from 参数来引用之前的阶段的镜像。

bash
docker build -t imagename:tag .

只构建某一阶段的镜像

我们可以使用 AS 来为某一阶段命名,例如:

dockerfile
FROM golang:alpine AS builder

例如当我们只想构建 builder 阶段的镜像时,增加 --target=builder 参数即可:

bash
docker build --target builder -t imagename:tag .

构建时从其他镜像复制文件

上面例子中我们使用 COPY --from=0 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。

dockerfile
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

环境变量会在多阶段中共享吗

在多阶段构建中,使用 ENV 指令设置的环境变量在多个构建阶段之间是不共享的。每个构建阶段都有自己的环境,并且 ENV 指令在每个阶段都会创建一个新的环境变量。

要在多个构建阶段之间共享环境变量,可以使用 ARG 指令将构建参数传递给多个阶段,然后在每个阶段中使用 ARG 指令设置环境变量。

下面的示例演示了如何在多个构建阶段之间共享环境变量:

dockerfile
ARG VERSION=latest
FROM alpine:${VERSION} AS build
ARG VERSION
RUN echo ${VERSION} > /version

FROM alpine:${VERSION}
ARG VERSION
ENV VERSION=${VERSION}
COPY --from=build /version /version