用 Docker 编译软件,是用 build 好还是用 build+run 好? - V2EX
请不要在回答技术问题时复制粘贴 AI 生成的内容
msg7086

用 Docker 编译软件,是用 build 好还是用 build+run 好?

  •  
  •   msg7086
    msg7086 Aug 9, 2019 3811 views
    This topic created in 2487 days ago, the information mentioned may be changed or developed.

    背景

    在维护一堆开源软件,因为需要比较固定可靠的编译环境,所以之前导入了 Docke,在 Dockerfile 里拉操作系统装依赖签出源码然后编译。编译完成后 run 一秒复制出成品然后销毁。

    每次开源软件更新时,重新 pull 底层操作系统镜像,重新构建编译环境,然后重新编译和打包发布。当然,新的系统发布的时候也是要为新系统编译的。

    问题

    单纯使用 Dockerfile build 从零到编译完是否是最佳实践?

    记得以前还看到过一个做法是 build 只准备环境,然后用 run 来编译。这种方式是不是更好的实践?

    两种做法各有什么利弊吗?

    延伸

    接下去打算发展 Docker for Windows,因为还要编译很多 Windows 下的开源项目。大家使用过程中有踩到什么坑吗?

    15 replies    2019-08-09 16:12:47 +08:00
    chendy
        1
    chendy  
       Aug 9, 2019
    build 准备环境,run 跑构建,没毛病
    momocraft
        2
    momocraft  
       Aug 9, 2019
    那你的 image 要包含所有 build deps?
    imherer
        3
    imherer  
       Aug 9, 2019
    buid > run > commit ?
    直接 build 出来就可以了呀,为什么还要 run ?
    GeruzoniAnsasu
        4
    GeruzoniAnsasu  
       Aug 9, 2019 via Android
    ……怀疑 lz 没有用过 ci pipeline
    ntdll
        5
    ntdll  
       Aug 9, 2019
    我的做法是 build 基础的构建环境,如 gcc、java 之类的。基础编译环境准备完毕后,通过 run 的时候,pull 代码,编译出目标文件
    msg7086
        6
    msg7086  
    OP
       Aug 9, 2019
    @momocraft image 里是有 build deps 的,编译完就可以删了,要的是编译出来的软件包。
    短期内多次对同一个操作系统进行编译的话,可以重用之前的文件层,我觉得还是挺方便的?

    @imherer
    build 本身能把镜像里编译好的文件复制出来么?
    我现在是 build 完以后创建镜像然后把文件 cp 出来的。
    (刚刚看了一下脚本,用的是 container cp,不是 run )

    @GeruzoniAnsasu 没有怎么用过。能否冒昧请教一下怎么用在这个场景下?
    jingxyy
        7
    jingxyy  
       Aug 9, 2019
    我喜欢 run 时候-v 映射一个本地目录进去 编译完的放这个目录
    zjsxwc
        8
    zjsxwc  
       Aug 9, 2019
    build 是用来运行构建环境的,
    run 是作为工具提供给别人用的,
    因为并不知道别人要编译哪些文件,所以 run 更灵活,而 build 需要写死等待被编译的文件
    msg7086
        9
    msg7086  
    OP
       Aug 9, 2019
    @zjsxwc 我这边只是自己用,编译也只编译特定的大型项目,不考虑其他人使用,也不考虑编译其他软件的。
    whileFalse
        10
    whileFalse  
       Aug 9, 2019
    如果不想让最终运行用镜像包含源码和 Compile-time 的话,用 Docker 的多阶段构建

    https://docs.docker.com/develop/develop-images/multistage-build/
    whileFalse
        11
    whileFalse  
       Aug 9, 2019   1
    或者如果你只想要一个干净的编译环境以获取可以在外部运行的二进制的话,你的方式是对的。
    mmtromsb456
        12
    mmtromsb456  
       Aug 9, 2019   1
    就我个人用 docker 差不多两年的经验来理解的话,因为我自己也有在维护一份私人的 openwrt 编译环境,所以我觉得相对来说比较方便的实践是这样的.
    1.使用多阶段构建,在第一阶段中使用 dockerfile 中的 RUN 指令来构建出完整的所需二进制文件(whatever)
    2.在第二阶段构建中提取出所需的二进制文件到新容器(多阶段构建的本质是不同的容器)中
    3.在第二阶段的构建最后使用 COMMAND/ENTRYPOINT 等运行一个文件服务器进行分发
    4.docker run 这个最终容器,然后直接在别的渠道直接提取即可.当然如果不需要 remote wget/curl 的情况下.我个人认为第二阶段构建完全不需要指定 COMMAND/ENTRYPOINT.直接使用 cp 来复制也可以.
    我个人在使用的自动化编译流程基本上就是这样构成的,我理解是应该放在 COMMAND/ENTRYPOINT 的,也就是楼主你说的 run 的这个部分的应该有以下的特性:
    1.幂等的,无论是重建容器,还是失败后自动重启容器,都应该完成相同的工作,输出相同或者类似的结果
    2.轻量的,放在 run 的这个步骤的部分不应该阻塞启动时间,因为过长的启动时间会直接导致 docker 判断他启动失败.也不便于管理操作
    3.提供服务的,这个 run 基本上是面对使用者的最前面的内容,应该足够一目了然可以让使用者明白这个 run 直接的提供我需要的服务
    mmtromsb456
        13
    mmtromsb456  
       Aug 9, 2019
    或者如果准备环境以及编译同时是两个不同的步骤,完全可以首先维护一份准备环境的基底镜像,比如 sample/debian-with-gcc 这样.然后在开始编译的镜像中直接使用 FROM sample/debian-with-gcc 然后再进一步的书写需要的编译步骤.最终 docker build 完成编译.
    mmtromsb456
        14
    mmtromsb456  
       Aug 9, 2019
    这样的话,编译环境和编译操作可以达成解耦,分开维护非常方便
    msg7086
        15
    msg7086  
    OP
       Aug 9, 2019
    @mmtromsb456
    #12 你说的办法的话,应该和我现在用的是一样的了。也就是构建产生镜像以后,把镜像中的软件包 cp 出来。
    建立文件服务器好像是有点多余了,毕竟只有我自己用。

    #13 准备环境这个本来就是 dockerfile 中的一步。因为我们维护的软件就是支持现在所有的 Debian 和 Ubuntu 的,所以大概有 10 个不同的操作系统要编译。现在的 dockerfile 就是 from 拿了以后 apt 装环境,git 拉源码和依赖,然后编译打包出 deb。每个操作系统都需要更新到最新版本,所以我觉得分开维护十个基底镜像意义不大,每次还是要 pull 刷新了刷新的。
    About     Help     Advertise     Blog     API     FAQ     Solana     2948 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 57ms UTC 03:14 PVG 11:14 LAX 20:14 JFK 23:14
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86