Docker Compose与多阶段构建 [英] Docker Compose vs Multi-Stage Build

查看:48
本文介绍了Docker Compose与多阶段构建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用此新版本在Docker中,引入了Multi-Stage构建,至少我以前从未听说过.现在我的问题是,我应该像标准的Compose文件一样使用它吗?

我使用 docker-compose.yaml 来启动容器,其中涉及许多图像,一个用于Web服务器,一个用于数据库.通过这种新的多阶段构建,我可以将一个 Dockerfile 与两个 FROM 命令一起使用吗?

这种多阶段构建最终会杀死Compose(因为图像较小)吗?

解决方案

多阶段构建不会影响docker-compose的使用(尽管您可能希望使用 docker stack deploy 蜂群模式以在蜂群上使用该模式).仍然需要Compose才能将多个微服务连接在一起,例如运行代理,一些应用程序和内存缓存.Compose还简化了将所有配置选项传递到复杂的Docker映像,附加网络和卷,配置重启策略,群集约束等的情况.所有这些都可以通过许多脚本来完成,但是通过简单的yaml定义可以使操作变得更容易./p>

替换的多阶段构建是一个多步构建,其中您的构建环境可能与运行时环境不同.这一切都在运行容器的 docker-compose 配置之前.

流行的例子是go二进制文件.该二进制文件是静态编译的,因此实际上不需要任何其他操作.但是,由于它引入了编译器和各种库,因此其构建环境要大得多.这是一个hello.go示例:

 程序包主要导入"fmt"func main(){fmt.Printf(你好,世界.\ n")} 

以及相应的Dockerfile:

  ARGOLA_VER = 1.8来自golang:$ {GOLANG_VER}作为生成器WORKDIR/go/src/app复制 ..RUN go-wrapper下载RUN go-wrapper安装从头开始复制--from = builder/go/bin/app/appCMD ["/app"] 

Dockerfile的两条 FROM 行使它成为一个多阶段构建.第一行 FROM 使用go编译器创建第一阶段.第二行 FROM 也是最后一行,这使它成为构建时要标记的默认图像.在这种情况下,该阶段是单个二进制文件的运行时.其他阶段都缓存在构建服务器上,但不会与最终映像一起复制.如果需要使用 docker build --target = builder.命令来构建单个模块,则可以将构建目标定位到不同的阶段.

当您查看构建结果时,这一点很重要:

  $ docker build -t test-mult-stage.将构建上下文发送到Docker守护程序4.096kB第1/9步:ARG GOLANG_VER = 1.8--->第2/9步:从golang:$ {GOLANG_VER}作为生成器--->a0c61f0b0796步骤3/9:WORKDIR/go/src/app--->使用缓存--->af5177aae437步骤4/9:复制..--->使用缓存--->976490d44468步骤5/9:运行go-wrapper下载--->使用缓存--->e31ac3ce83c3步骤6/9:运行go-wrapper安装--->使用缓存--->2630f482fe78步骤7/9:从头开始--->步骤8/9:复制--from = builder/go/bin/app/app--->96b9364cdcdc卸下中间容器ED558A4DA820步骤9/9:CMD/app--->在55db8ed593ac中运行--->5fd74a4d4235卸下中间容器55db8ed593ac成功构建5fd74a4d4235成功标记了test-mult-stage:latest$泊坞窗图片|grep 2630< none>< none>2630f482fe78 5周前700MB$泊坞窗图片|grep test-mult阶段test-mult-stage最新5fd74a4d4235 33秒前1.56MB 

请注意,运行时映像仅为1.5 MB,而编译器未使用的生成器映像为700MB.以前,要获得相同的空间节省,您将需要在docker之外编译应用程序,并处理docker通常为您解决的所有依赖项问题.或者,您可以在一个容器中进行构建,将结果复制出该容器,然后将该复制的文件用作另一构建的输入.多阶段构建将第二个选项转换为单个可复制且可移植的命令.

With this new version of Docker, Multi-Stage build gets introduced, at least I'd never heard of it before. And the question I have now is, should I use it like a standard Compose file?

I used docker-compose.yaml to start containers where many images where involved, one for the web server and one for the data base. With this new multi-stage build, can I use one single Dockerfile with two FROM commands and that's it?

Will this Multi-stage build eventually kill Compose (since images are smaller)?

解决方案

Multi-stage builds don't impact the use of docker-compose (though you may want to look into using docker stack deploy with swarm mode to use that compose on a swarm). Compose is still needed to connect multiple microservices together, e.g. running a proxy, a few applications, and an in memory cache. Compose also simplifies passing all the configuration options to a complex docker image, attaching networks and volumes, configuring restart policies, swarm constraints, etc. All of these could be done with lots of scripting, but are made easier by a simple yaml definition.

What multi-stage builds do replace is a multiple step build where you may have a build environment that should be different than a runtime environment. This is all prior to the docker-compose configuration of running your containers.

The popular example is a go binary. That binary is statically compiled so it doesn't really need anything else to run. But the build environment for it is much larger as it pulls in the compiler and various libraries. Here's an example hello.go:

package main
import "fmt"
func main() {
        fmt.Printf("Hello, world.\n")
}

And the corresponding Dockerfile:

ARG GOLANG_VER=1.8
FROM golang:${GOLANG_VER} as builder
WORKDIR /go/src/app
COPY . .
RUN go-wrapper download 
RUN go-wrapper install

FROM scratch
COPY --from=builder /go/bin/app /app
CMD ["/app"]

The two FROM lines that that Dockerfile are what make it a multi-stage build. The first FROM line creates the first stage with the go compiler. The second FROM line is also the last which makes it the default image to tag when you build. In this case, that stage is the runtime of a single binary. Other stages are all cached on the build server but don't get copied with the final image. You can target the build to different stages if you need to build a single piece with the docker build --target=builder . command.

This becomes important when you look at the result of the build:

$ docker build -t test-mult-stage .
Sending build context to Docker daemon  4.096kB
Step 1/9 : ARG GOLANG_VER=1.8
 ---> 
Step 2/9 : FROM golang:${GOLANG_VER} as builder
 ---> a0c61f0b0796
Step 3/9 : WORKDIR /go/src/app
 ---> Using cache
 ---> af5177aae437
Step 4/9 : COPY . .
 ---> Using cache
 ---> 976490d44468
Step 5/9 : RUN go-wrapper download
 ---> Using cache
 ---> e31ac3ce83c3
Step 6/9 : RUN go-wrapper install
 ---> Using cache
 ---> 2630f482fe78
Step 7/9 : FROM scratch
 ---> 
Step 8/9 : COPY --from=builder /go/bin/app /app
 ---> 96b9364cdcdc
Removing intermediate container ed558a4da820
Step 9/9 : CMD /app
 ---> Running in 55db8ed593ac
 ---> 5fd74a4d4235
Removing intermediate container 55db8ed593ac
Successfully built 5fd74a4d4235
Successfully tagged test-mult-stage:latest

$ docker images | grep 2630
<none>          <none>      2630f482fe78    5 weeks ago      700MB

$ docker images | grep test-mult-stage
test-mult-stage latest      5fd74a4d4235    33 seconds ago   1.56MB

Note the runtime image is only 1.5 MB, while the untaged builder image with the compiler is 700MB. Previously to get the same space savings you would need to compile your application outside of docker and deal with all the dependency issues that docker would normally solve for you. Or you could do the build in one container, copy the result out of that container, and use that copied file as the input to another build. The multi-stage build turns this second option into a single reproducible and portable command.

这篇关于Docker Compose与多阶段构建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆