为了编写一个真正高效的Dockerfile,传统上需要使用shell技巧和其他逻辑来保持层尽可能小,并确保每个层都具有前一层所需的工件而不是其他任何东西。
实际上,有一个Dockerfile用于开发(包含构建应用程序所需的所有内容),以及用于生产环境的精简版Dockerfile,它只包含您的应用程序以及运行它所需的内容。这被称为“建造者模式”。维护两个Dockerfiles并不理想。
这是一个Dockerfile.build和Dockerfile的例子,它遵循上面的模式:
Dockerfile.build:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go .
RUN go get -d -v golang.org/x/net/html \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
Dockerfile:
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]
build.sh:
echo Building alexellis2/href-counter:build
docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy \
-t alexellis2/href-counter:build . -f Dockerfile.build
docker container create --name extract alexellis2/href-counter:build
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app
docker container rm -f extract
echo Building alexellis2/href-counter:latest
docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app
多阶段构建大大简化了这种情况!
使用多阶段构建
为了说明这是如何工作的,让我们调整上述示例的Dockerfile以使用多阶段构建。
Dockerfile:
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
您只需要单个Dockerfile。您也不需要单独的构建脚本。只需运行docker build:
最终结果是产生与之前相同大小的image,复杂性显著降低。您不需要创建任何中间image,也不需要将任何artifacts提取到本地系统。$ docker build -t app:latest .
它是如何工作的?第二个FROM指令以alpine:latest image为基础开始一个新的构建阶段。
COPY –from = 0行仅将前一阶段的构建文件复制到此新阶段。Go SDK和任何中间层都被遗忘,而不是保存在最终image中。
为多构建阶段命名
但是,您可以通过向FROM指令添加as NAME来命名您的阶段。此示例通过命名阶段并使用COPY指令中的名称来改进前一个示例。
这意味着即使稍后重新排序Dockerfile中的指令,COPY也不会中断。
FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
停在特定的构建阶段
您可以指定目标构建阶段。以下命令假定您使用的是以前的Dockerfile,但在名为builder的阶段停止:
$ docker build --target builder -t alexellis2/href-counter:latest .
调试特定的构建阶段
在debug阶段,启用所有调试或工具,而在production阶段尽量精简
在testing阶段,您的应用程序将填充测试数据,但在production阶段则使用生产数据
使用外部镜像作为stage
您还可以使用COPY –from指令从单独的image中复制,使用本地image名称,本地或Docker注册表中可用的标记或标记ID。
如有必要,Docker会提取image并从那里开始复制。
语法是:
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
原文链接:https://wilhelmguo.tk/blog/post/william/Docker构建之多阶段构建