在多阶构建出来之前使用单个文件进行构建,单文件就是将所有的构建过程(包括项目的依赖、编译、测试、打包过程)全部包含在一个Dockerfile中之下:
- FROM golang:1.11.4-alpine3.8 AS build-env
- ENV GO111MODULE=off
- ENV GO15VENDOREXPERIMENT=1
- ENV BUILDPATH=github.com/lattecake/hello
- RUN mkdir -p /go/src/${BUILDPATH}
- COPY ./ /go/src/${BUILDPATH}
- RUN cd /go/src/${BUILDPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install –v
-
- CMD [/go/bin/hello]
这种的做法会带来一些问题:
- Dockerfile文件会特别长,当需要的东西越来越多的时候可维护性指数级将会下降;
- 镜像层次过多,镜像的体积会逐步增大,部署也会变得越来越慢;
- 代码存在泄漏风险。
以Golang为例,它运行时不依赖任何环境,只需要有一个编译环境,那这个编译环境在实际运行时是没有任务作用的,编译完成后,那些源码和编译器已经没有任务用处了也就没必要留在镜像里。
上表可以看到,单文件构建最终占用了312MB的空间。
2. 多文件构建
在多阶构建出来之前有没有好的解决方案呢?有,比如采用多文件构建或在构建服务器上安装编译器,不过在构建服务器上安装编译器这种方法我们就不推荐了,因为在构建服务器上安装编译器会导致构建服务器变得非常臃肿,需要适配各个语言多个版本、依赖,容易出错,维护成本高。所以我们只介绍多文件构建的方式。
多文件构建,其实就是使用多个Dockerfile,然后通过脚本将它们进行组合。假设有三个文件分别是:Dockerfile.run、Dockerfile.build、build.sh。
- Dockerfile.run就是运行时程序所必须需要的一些组件的Dockerfile,它包含了最精简的库;
- Dockerfile.build只是用来构建,构建完就没用了;
- build.sh的功能就是将Dockerfile.run和Dockerfile.build进行组成,把Dockerfile.build构建好的东西拿出来,然后再执行Dockerfile.run,算是一个调度的角色。
Dockerfile.build
- FROM golang:1.11.4-alpine3.8 AS build-env
- ENV GO111MODULE=off
- ENV GO15VENDOREXPERIMENT=1
- ENV BUILDPATH=github.com/lattecake/hello
- RUN mkdir -p /go/src/${BUILDPATH}
- COPY ./ /go/src/${BUILDPATH}
- RUN cd /go/src/${BUILDPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install –v
Dockerfile.run
- FROM alpine:latest
- RUN apk –no-cache add ca-certificates
- WORKDIR /root
- ADD hello .
- CMD ["./hello"]
(编辑:PHP编程网 - 黄冈站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|