Golang Go语言中docker build 项目每次都很慢,有什么好的办法吗?

Golang Go语言中docker build 项目每次都很慢,有什么好的办法吗?

  • 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,它不会自己缓存吗?

求大佬解答


更多关于Golang Go语言中docker build 项目每次都很慢,有什么好的办法吗?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

27 回复

你在镜像里面构建 go,怎么会缓存- -
可以先构建完代码,把二进制 copy 进容器里面

更多关于Golang Go语言中docker build 项目每次都很慢,有什么好的办法吗?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你可以选择用 vendor

没有合理的利用缓存,改成下面这样就快了

dockerfile<br>ADD go.mod .<br>ADD go.sum .<br><br>RUN export GO111MODULE=on &amp;&amp; \<br> export GOPROXY=<a target="_blank" href="https://goproxy.cn" rel="nofollow noopener">https://goproxy.cn</a> &amp;&amp; \<br> go mod download<br><br>COPY . .<br><br>RUN go build -o main main.go<br>

这不是穿上裤子放屁么
直接光屁股编译还能用上本地缓存

是因为 COPY . . 在 go mod download 前面,会导致下面 go mod download 也重建了,放到缓存之后就可以了

因为缓存不在你当前文件夹,你镜像里并没有缓存。楼上说的用 vender 可以,但是改变比较大。
也可以将镜像的缓存目录挂载到本地。
也可以不要每次都用 makefile 建立新的镜像,开发的时候用一个镜像将代码挂在进去。
方法很多,你这个是最离谱的。

docker 在 build 的时候 Dockerfile 中每个 RUN 最终都会是独立容器运行, 你这样等于没用, 反而增加构建之后 image 体积

c# go maven gradle 的统一解决思路:
1. 仅拷贝依赖清单
2. 下载依赖
3. 拷贝所有文件
4. 编译

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

#3 楼的貌似是对的(我没用过 docker go )

先编译好 copy/add 进去不好么

谢谢大佬, 确实快了很多,是不是 copy . . 放在前面导致 2 次 go mod download 呀

谢谢大佬,copy . . 放在前面会导致 2 次 go mod download 吗?

镜像里面放编译产物
不要在镜像里面编译

在本地编译出二进制文件,再 copy 进镜像
FROM alpine

COPY main /

CMD ["/main"]

3 秒结束

如果不在镜像里面编译,是在本地编译好?还是在宿主机编译呢?这个有速度区别嘛

本地编译也要花时间的吧。。 另外如果本地 macos 环境编译,线上 centos 环境,不会存在环境不兼容都问题吗?

#14 都差不多,区别在于,放在外面编译的话,可以直接用已经下载好的 go modules 啥的,要在镜像里面的话,因为里面没有缓存,每次都得重新下载

这样的编译方式第一次见··

如果是人手打包的话, 当然是本地编译后 COPY 进 alpine 最快

如果是 ci 的话,当然是 Dockerfile 里编译更佳. 宁可多一层 image 也不要多加一个脚本.

mac 和 centos 不兼容。你也可以看看 multi stage docker

本地交叉编译。。。

Go 语言构建 docker 只需要 4 行代码,build, from, copy, cmd 结束了。

如果对测试特性没有什么心理障碍的话,可以试试这个

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

可以缓存编译的中间产物

如果只是为了 go 跨平台编译用 docker,根本不需要,go 本身就支持交叉编译。

理论上你不清理 docker 的临时镜像重新 build 的时候就会复用安装依赖时的镜像,先将依赖配置拷贝进容器,下载安装完依赖后再拷贝源码,这样就会复用之前的镜像(除非你是更改了依赖配置)。这样 docker 构建就快很多了。

话说 go 编译速度真的不算慢的,要不你去试试 java (doge)

相反,我把本地交叉编译改成 在 paas 里面编译了,本地 mac,paas:go-alpine 。 并不觉得慢,换个 goproxy 试试?

docker 的多阶段构建可以帮助你去掉没用的源码,最后只保留编译好的二进制文件。

可以参考: https://github.com/crawlab-team/crawlab/blob/master/Dockerfile

在Golang项目中,使用Docker进行构建时遇到速度慢的问题,通常可以通过以下几种方法来优化:

  1. 利用Docker缓存:确保你的Dockerfile编写得当,以便Docker可以利用缓存来加速构建。例如,将依赖安装和代码复制分开成不同的层,这样当依赖没有变化时,可以直接使用缓存的层。

  2. 多阶段构建:使用Docker的多阶段构建来减少最终镜像的大小和构建时间。在构建阶段使用完整的编译环境,而在最终阶段仅包含必要的运行时文件。

  3. 选择合适的基础镜像:选择更小、更轻量的基础镜像可以减少下载时间和构建时间。例如,使用Alpine Linux作为基础镜像通常会比使用Ubuntu等更轻量。

  4. 并行构建:如果可能,尝试在Dockerfile中使用并行构建工具或命令,以充分利用多核CPU的优势。

  5. 本地缓存依赖:在构建Docker镜像之前,先在本地环境中缓存Go项目的依赖(如使用go mod download),这样可以在Docker构建过程中避免下载这些依赖。

  6. 增加构建机器的资源:如果构建机器的资源(如CPU、内存、网络带宽)有限,考虑升级硬件或使用更高配置的云服务。

  7. 使用构建缓存服务:考虑使用如BuildKit等支持构建缓存的服务,它们可以显著提高构建速度。

通过上述方法,你应该能够显著减少Golang项目在Docker中的构建时间。

回到顶部