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

2020-12-01 17:03:59 +08:00
 caicaiwoshishui
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,它不会自己缓存吗?

求大佬解答

5931 次点击
所在节点    Go 编程语言
26 条回复
junnplus
2020-12-01 17:11:04 +08:00
你在镜像里面构建 go,怎么会缓存- -
可以先构建完代码,把二进制 copy 进容器里面
kkbblzq
2020-12-01 17:16:12 +08:00
你可以选择用 vendor
zealic
2020-12-01 17:24:13 +08:00
没有合理的利用缓存,改成下面这样就快了

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

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

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

COPY main /

CMD ["/main"]

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

如果是 ci 的话,当然是 Dockerfile 里编译更佳. 宁可多一层 image 也不要多加一个脚本.
julyclyde
2020-12-01 19:04:27 +08:00
@caicaiwoshishui mac 和 centos 不兼容。你也可以看看 multi stage docker
junnplus
2020-12-01 20:29:40 +08:00
@julyclyde @caicaiwoshishui 本地交叉编译。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/731045

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX