多级构建与yum

时间:2018-04-13 20:58:02

标签: docker

我正在努力将我当前的dockerfiles转换为多阶段构建以减少一些错误。我从一个基本映像开始,通过yum安装一堆东西以及我从源代码安装的一堆其他软件包。

此时,我想从一个新的图像开始,只引入通过yum安装的软件包和来自我的安装源的二进制文件。我看到有三种方法可以做到这一点,但我不喜欢第一种选择,也不知道如何做其他两种方法。

选项1

为yum install构建一个单独的Dockerfile,然后在从源安装之前将其用作我的基本映像。

我不喜欢这个选项,因为它为我的构建工作流程增加了更多。将所有内容都包含在一个Dockerfile中会很不错。也许这就是我需要的方式。

选项2

通过yum在不同的目录中安装软件包,然后复制到构建的下一个阶段。

我发现我可以通过yum install --installroot=/foo --releasever=/ packagename在非默认目录中安装软件包,但是,这会将所有需求安装到/ foo,而不是继续使用/ usr中安装的软件包,从而导致图像显着增长。

有没有办法通过yum在不同的目录中安装软件包,但让它继续从默认目录中解析其依赖项?

选项3

通过yum安装软件包,然后从安装yum软件包之后的点开始下一个构建阶段。

有没有办法将构建阶段产生的图层用作下一个构建阶段的开始?像这样:

FROM centos7 as first
RUN some stuff
FROM first as second
RUN some stuff
FROM second
COPY --from=second ...

3 个答案:

答案 0 :(得分:2)

使用多阶段构建

对于多阶段构建,您可以在Dockerfile中使用多个 FROM 语句。每个 FROM 指令可以使用不同的基础,并且每个指令都开始构建的新阶段。您可以有选择地将工件从一个阶段复制到另一个阶段,从而在最终图像中留下不需要的所有内容。为了说明它是如何工作的,请考虑以下示例:

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 alexellis2/href-counter:latest .

最终结果是微小的生产图像,大大降低了复杂性。您不需要创建任何中间图像,也不需要将任何工件提取到本地系统中。

它如何工作?

第二条 FROM 指令以 alpine:latest 映像为基础开始新的构建阶段。 COPY --from = 0 行仅将先前阶段的构建工件复制到新阶段。 Go SDK和所有中间工件都被保留了下来,没有保存在最终图像中。

答案 1 :(得分:0)

我不确定这是否可以通过Docker来实现,但这似乎是http://drone.io/的一个很好的用例 您可以在构建的不同阶段使用不同的映像,然后仅在最终的Docker映像上使用所需的文件。

答案 2 :(得分:0)

对于选项1,您有正确的想法,但对于多阶段构建,可以通过使用3阶段构建而不是单独的基本映像docker文件来实现。

使用named stagescopying from a previous stagestarting a stage from a previous stage的组合,结果如下所示。

FROM centos:latest AS yum-base
RUN yum install -y LIST_OF_YUM_DEPENDENCIES
...

FROM yum-base AS compiled_packages
RUN build_some_binaries_here
...

FROM yum-base
COPY --from=compiled_packages /usr/local/bin/file_name /usr/local/bin/file_name