在Docker中缓存Go依赖项

huangapple go评论73阅读模式
英文:

Caching Go Depencencies in Docker

问题

我已经阅读了文章,其中建议为下载Go依赖项设置一个专用的go mod download层。我理解这个层会被缓存,如果依赖项在下一次构建中没有更改,将会使用缓存的层,从而节省时间。
我还注意到使用BuildKit的挂载功能,go build二进制结果会被缓存在GO env GOCACHE目录中,以便于将来的构建使用。

现在的问题是,很多时候只有少数几个Go依赖项发生了变化,因此缓存的go mod download层会失效。结果,在下一次构建中,所有的依赖项都会被重新下载,即使只有其中几个发生了变化。
我的问题是,如果将已下载的包(依赖项)挂载上去,这样做是否可以?这样做的缺点是什么?我没有看到这种技术在Go Dockerfile的最佳实践中被使用。
类似于

RUN --mount=type=cache,target=/go/pkg/mod go mod download
英文:

I've read articles in which it is advised to have a dedicated go mod download layer for downloading go dependencies. I understand that the layer is cached and if the dependencies don't change in the next build, the cached layer will be used, saving us time.
I've also noticed that using BuildKit mounting feature, the go build binary results are cached in GO env GOCACHE directory, in order to be used for future builds.

Now the thing is a lot of the time only a few of the go dependencies are changed, therefore the cached go mod download layer is invalidated. And as a result, in the next build, all the dependencies will be downloaded again, even if only a few of them have changed.
My question is if is ok to mount the downloaded packages (dependencies)? And what would be the downsides of doing that? I haven't seen this technique to be used in Go Dockerfile best practices.
Something like

RUN --mount=type=cache,target=/go/pkg/mod go mod download

答案1

得分: 4

我认为你可以直接开始尝试并观察结果。如果我要使用这个命令,我会选择一个不同的挂载路径,以便隔离本地环境。

RUN --mount=type=cache,target=/Users/me/Library/Caches go mod download

我认为挂载已下载的包没有任何问题。在这个示例中,它被用于apt

然而,我认为我们也可以退一步,考虑不受等待Docker构建的困扰的不同方法。

我们可以进行定期构建(夜间构建等),我认为没有理由频繁进行本地Docker构建,特别是你的依赖项不应该经常更改。也许我错了,但我认为我们不需要这样做。

我们还可以进一步拆分go mod download并利用Docker构建缓存。
例如:

RUN go mod download package-never-change
RUN go mod download package-changes-frequently

甚至可以这样:

RUN go build ./package1
RUN go build ./package2

这可能看起来有点繁琐,但在某些情况下可能很有用,例如不支持BuildKit的情况。

英文:

I think you can just start doing that and see. For me, if I had to use this, I would choose a different mount path, just to isolate the local environment.

RUN --mount=type=cache,target=/Users/me/Library/Caches go mod download

I don't see any problem mounting downloaded packages. In this example, it is used for apt.

However, I think we can also take a step back and consider different approaches to not to be bothered by waiting for Docker build.

We can have scheduled builds (nightly build and etc), I don't see any reason to do local docker build that frequent, especially your dependencies shouldn't change that often. Maybe I am wrong, but I don't think we need to.

We can also further break down go mod download and leverage Docker build cache
E.g.

RUN go mod download package-never-change
RUN go mod download package-changes-frequently

Even

RUN go build ./package1
RUN go build ./package2

It maybe look a little bit tedious, but under certain circumstances it could be useful, for example, when BuildKit is not supported.

huangapple
  • 本文由 发表于 2022年3月15日 16:18:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/71478963.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定