【问题标题】:Multistage builds with yum使用 yum 进行多阶段构建
【发布时间】:2018-09-24 06:54:46
【问题描述】:

我正在努力将我当前的 dockerfile 转换为多阶段构建以减少一些麻烦。我从一个基础镜像开始,通过 yum 安装一堆东西以及我从源代码安装的一堆其他包。

此时,我想从一个全新的镜像开始,只引入通过 yum 安装的软件包和我从源代码安装的二进制文件。我看到了三种方法可以做到这一点,但我不喜欢第一个选项,也不知道如何做另外两个。

选项 1

为 yum 安装构建一个单独的 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 ...

【问题讨论】:

  • 嘿,你找到办法了吗?
  • 其实,没有。我刚刚不得不处理变通方法......大多数情况下我只使用“选项 1”。
  • 这样做有什么好处?如果您想优化构建时间,docket build 已经做到了,因为它只是构建与上次构建的差异。如果您不重用基础镜像,为什么不坚持使用单个 Dockerfile?
  • 这与构建时间无关。这与图像大小有关。构建一些二进制文件会留下太多垃圾。
  • 分享你当前的 dockerfile

标签: docker


【解决方案1】:

我不确定这是否可以通过 Docker 实现,但它看起来像是 http://drone.io/ 的一个很好的用例 你可以在构建的不同阶段使用不同的镜像,然后在最终的 docker 镜像上只使用你想要的文件。

【讨论】:

    【解决方案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 和任何中间工件都被留下,不会保存在最终图像中。

    【讨论】:

      【解决方案3】:

      您对选项 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
      

      【讨论】:

        猜你喜欢
        • 2022-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-18
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 2015-12-08
        相关资源
        最近更新 更多