docker build go 项目每次都很慢,有什么好的办法吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
caicaiwoshishui
V2EX    Go 编程语言

docker build go 项目每次都很慢,有什么好的办法吗?

  •  
  •   caicaiwoshishui 2020-12-01 17:03:59 +08:00 6400 次点击
    这是一个创建于 1774 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • dockerfile 部分内容
    COPY . . ADD go.mod . ADD go.sum . RUN export GO111MODULE=on && \ export GOPROXY=https://goproxy.cn && \ go mod download RUN go build -o main main.go 

    接触 golang 没多久,是不是姿势不对呀? mod 没有更新的情况,为啥每次都 go mod download,它不会自己缓存吗?

    求大佬解答

    第 1 条附言    2020-12-02 09:39:35 +08:00
    感谢大家,特别是三楼的兄弟,编译速度减少至 3 分钟了。
    26 条回复    2020-12-01 22:12:15 +08:00
    junnplus
        1
    junnplus  
       2020-12-01 17:11:04 +08:00   1
    你在镜像里面构建 go,怎么会缓存- -
    可以先构建完代码,把二进制 copy 进容器里面
    kkbblzq
        2
    kkbblzq  
       2020-12-01 17:16:12 +08:00   1
    你可以选择用 vendor
    zealic
        3
    zealic  
       2020-12-01 17:24:13 +08:00   2
    没有合理的利用缓存,改成下面这样就快了

    ```dockerfile
    ADD go.mod .
    ADD go.sum .

    RUN export GO111MODULE=on && \
    export GOPROXY=https://goproxy.cn && \
    go mod download

    COPY . .

    RUN go build -o main main.go
    ```
    julyclyde
        4
    julyclyde  
       2020-12-01 17:24:22 +08:00   1
    这不是穿上裤子放屁么
    直接光屁股编译还能用上本地缓存
    Mitt
        5
    Mitt  
       2020-12-01 17:27:03 +08:00 via iPhone   1
    是因为 COPY . . 在 go mod download 前面,会导致下面 go mod download 也重建了,放到缓存之后就可以了
    Vegetable
        6
    Vegetable  
       2020-12-01 17:32:42 +08:00   1
    因为缓存不在你当前文件夹,你镜像里并没有缓存。楼上说的用 vender 可以,但是改变比较大。
    也可以将镜像的缓存目录挂载到本地。
    也可以不要每次都用 makefile 建立新的镜像,开发的时候用一个镜像将代码挂在进去。
    方法很多,你这个是最离谱的。
    hteen
        7
    hteen  
       2020-12-01 17:46:32 +08:00   1
    docker 在 build 的时候 Dockerfile 中每个 RUN 最终都会是独立容器运行, 你这样等于没用, 反而增加构建之后 image 体积
    crclz
        8
    crclz  
       2020-12-01 17:51:25 +08:00   2
    c# go maven gradle 的统一解决思路:
    1. 仅拷贝依赖清单
    2. 下载依赖
    3. 拷贝所有文件
    4. 编译

    如果第一步的依赖清单不改变,那么第二步开始的时候,docker 检测到校验和是相同的,所以 docker 会直接使用缓存。

    #3 楼的貌似是对的(我没用过 docker go )
    xuanbg
        9
    xuanbg  
       2020-12-01 17:51:30 +08:00
    先编译好 copy/add 进去不好么
    caicaiwoshishui
        10
    caicaiwoshishui  
    OP
       2020-12-01 17:58:15 +08:00
    @zealic 谢谢大佬, 确实快了很多,是不是 copy . . 放在前面导致 2 次 go mod download 呀
    caicaiwoshishui
        11
    caicaiwoshishui  
    OP
       2020-12-01 17:58:55 +08:00
    @Mitt 谢谢大佬,copy . . 放在前面会导致 2 次 go mod download 吗?
    boris93
        12
    boris93  
       2020-12-01 18:00:50 +08:00 via Android   1
    镜像里面放编译产物
    不要在镜像里面编译
    TypeErrorNone
        13
    TypeErrorNone  
       2020-12-01 18:13:46 +08:00
    在本地编译出二进制文件,再 copy 进镜像
    FROM alpine

    COPY main /

    CMD ["/main"]

    3 秒结束
    caicaiwoshishui
        14
    caicaiwoshishui  
    OP
       2020-12-01 18:14:38 +08:00
    @boris93 如果不在镜像里面编译,是在本地编译好?还是在宿主机编译呢?这个有速度区别嘛
    caicaiwoshishui
        15
    caicaiwoshishui  
    OP
       2020-12-01 18:16:26 +08:00
    @TypeErrorNone 本地编译也要花时间的吧。。 另外如果本地 macos 环境编译,线上 centos 环境,不会存在环境不兼容都问题吗?
    boris93
        16
    boris93  
       2020-12-01 18:37:20 +08:00 via Android
    @caicaiwoshishui #14 都差不多,区别在于,放在外面编译的话,可以直接用已经下载好的 go modules 啥的,要在镜像里面的话,因为里面没有缓存,每次都得重新下载
    ArJun
        17
    ArJun  
       2020-12-01 18:44:58 +08:00
    这样的编译方式第一次见
    f6x
        18
    f6x  
       2020-12-01 18:52:49 +08:00
    如果是人手打包的话, 当然是本地编译后 COPY 进 alpine 最快

    如果是 ci 的话,当然是 Dockerfile 里编译更佳. 宁可多一层 image 也不要多加一个脚本.
    julyclyde
        19
    julyclyde  
       2020-12-01 19:04:27 +08:00
    @caicaiwoshishui mac 和 centos 不兼容。你也可以看看 multi stage docker
    junnplus
        20
    junnplus  
       2020-12-01 20:29:40 +08:00
    @julyclyde @caicaiwoshishui 本地交叉编译。。。
    Hanggi
        21
    Hanggi  
       2020-12-01 20:34:50 +08:00
    Go 语言构建 docker 只需要 4 行代码,build, from, copy, cmd 结束了。
    guyeu
        22
    guyeu  
       2020-12-01 20:43:24 +08:00
    如果对测试特性没有什么心理障碍的话,可以试试这个

    https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/experimental.md#run---mounttypecache

    可以缓存编译的中间产物
    GG668v26Fd55CP5W
        23
    GG668v26Fd55CP5W  
       2020-12-01 21:14:23 +08:00 via iPhone
    如果只是为了 go 跨平台编译用 docker,根本不需要,go 本身就支持交叉编译。
    tikazyq
        24
    tikazyq  
       2020-12-01 22:10:24 +08:00
    理论上你不清理 docker 的临时镜像重新 build 的时候就会复用安装依赖时的镜像,先将依赖配置拷贝进容器,下载安装完依赖后再拷贝源码,这样就会复用之前的镜像(除非你是更改了依赖配置)。这样 docker 构建就快很多了。

    话说 go 编译速度真的不算慢的,要不你去试试 java (doge)
    shmilyoo
        25
    shmilyoo  
       2020-12-01 22:11:38 +08:00
    相反,我把本地交叉编译改成 在 paas 里面编译了,本地 mac,paas:go-alpine 。 并不觉得慢,换个 goproxy 试试?
    tikazyq
        26
    tikazyq  
       2020-12-01 22:12:15 +08:00
    docker 的多阶段构建可以帮助你去掉没用的源码,最后只保留编译好的二进制文件。

    可以参考: https://github.com/crawlab-team/crawlab/blob/master/Dockerfile
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     904 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 22:18 PVG 06:18 LAX 15:18 JFK 18:18
    Do have faith in what you're doing.
    ubao 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