Docker多阶段构建最佳实践

栏目: 服务器 · 发布时间: 6年前

内容简介:Docker目前在容器市场可以说是占领了大部分市场,Docker掀起了容器革命,同时也改变了现代化云平台的构建方式。尽管Docker很强大,但使用过程当中也遇到了一些问题。比如说我想要构建一个编译型语言镜像,需要先在一个Dockerfile中编译,然后再使用另外一个Dockerfile把编译好的文件放到镜像中。这样无形当中就增大了CI/CD的复杂度。Docker多阶段构建是17.05以后引入的新特性,旨在解决编译和构建复杂的问题。减小镜像大小。因此要使用多阶段构建特性必须使用高于或等于17.05的Dock

Docker目前在容器市场可以说是占领了大部分市场,Docker掀起了容器革命,同时也改变了现代化云平台的构建方式。尽管 Docker 很强大,但使用过程当中也遇到了一些问题。比如说我想要构建一个编译型语言镜像,需要先在一个Dockerfile中编译,然后再使用另外一个Dockerfile把编译好的文件放到镜像中。这样无形当中就增大了CI/CD的复杂度。

Docker多阶段构建是17.05以后引入的新特性,旨在解决编译和构建复杂的问题。减小镜像大小。因此要使用多阶段构建特性必须使用高于或等于17.05的Docker。

多阶段构建出现之前

构建镜像最具挑战性的一点是使镜像大小尽可能的小。Dockerfile中的每条指令都为图像添加了一个图层,您需要记住在移动到下一层之前清理任何不需要的工件。

为了编写一个真正高效的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 .

请注意,此示例使用Bash &&运算符人为压缩两个RUN命令,以避免在image中创建其他层。这很容易出错并且难以维护。

Dockerfile:

FROM alpine:latest  

RUN apk --no-cache add ca-certificates

WORKDIR /root/

COPY app .

CMD ["./app"]

build.sh:

#!/bin/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

当您运行build.sh脚本时,它需要构建第一个image,从中创建容器以复制工件,然后构建第二个image。

多阶段构建大大简化了这种情况!

使用多阶段构建

对于多阶段构建,您可以在Dockerfile中使用多个FROM语句。每个FROM指令可以使用不同的基础,并且每个指令都开始一个新的构建。您可以选择性地将工件从一个阶段复制到另一个阶段,从而在最终image中只留下您想要的内容。

为了说明这是如何工作的,让我们调整上述示例的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:

$ docker build -t app:latest .

最终结果是产生与之前相同大小的image,复杂性显著降低。您不需要创建任何中间image,也不需要将任何artifacts提取到本地系统。

它是如何工作的?第二个FROM指令以alpine:latest image为基础开始一个新的构建阶段。

COPY –from = 0行仅将前一阶段的构建文件复制到此新阶段。Go SDK和任何中间层都被遗忘,而不是保存在最终image中。

为多构建阶段命名

默认情况下,阶段未命名,您可以通过整数来引用它们,从第0个FROM指令开始。

但是,您可以通过向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每个阶段。

您可以指定目标构建阶段。以下命令假定您使用的是以前的Dockerfile,但在名为builder的阶段停止:

$ docker build --target builder -t alexellis2/href-counter:latest .

使用此功能可能的一些非常适合的场景是:

  • 调试特定的构建阶段
  • 在debug阶段,启用所有调试或工具,而在production阶段尽量精简
  • 在testing阶段,您的应用程序将填充测试数据,但在production阶段则使用生产数据

使用外部镜像作为stage

使用多阶段构建时,您不仅可以从Dockerfile中创建的镜像中进行复制。

您还可以使用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 构建之多阶段构建


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法心得:高效算法的奥秘(原书第2版)

算法心得:高效算法的奥秘(原书第2版)

(美)Henry S. Warren, Jr. / 爱飞翔 / 机械工业出版社 / 2014-3 / 89.00

【编辑推荐】 由在IBM工作50余年的资深计算机专家撰写,Amazon全五星评价,算法领域最有影响力的著作之一 Google公司首席架构师、Jolt大奖得主Hoshua Bloch和Emacs合作创始人、C语言畅销书作者Guy Steele倾情推荐 算法的艺术和数学的智慧在本书中得到了完美体现,书中总结了大量高效、优雅和奇妙的算法,并从数学角度剖析了其背后的原理 【读者评价......一起来看看 《算法心得:高效算法的奥秘(原书第2版)》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具