英文:
Download built modules to GOBIN using go.mod for Docker caching
问题
我有一个多阶段的Dockerfile(使用BuildKit),其中包含一个初始阶段,用于go get
我需要在后续阶段中使用的几个工具作为二进制文件。
以下示例是其要点:
# syntax = docker/dockerfile:1.0-experimental
# Go build stage
FROM golang:1.14-alpine3.12 AS gobuild
RUN apk add --no-cache git
RUN GO111MODULE=on go get -v github.com/tool1/tool1
RUN GO111MODULE=on go get -v github.com/tool2/tool2
RUN GO111MODULE=on go get -v github.com/tool3/tool3
# ...
# Release stage
FROM base AS release
# Copy Go binaries
COPY --from=gobuild /go/bin/tool1 /usr/local/bin/tool1
COPY --from=gobuild /go/bin/tool2 /usr/local/bin/tool2
COPY --from=gobuild /go/bin/tool3 /usr/local/bin/tool3
# ...
这个方法很有效。我唯一的问题是每次docker build
都需要重新下载Go Modules,也就是说它们没有被缓存。
经过一些研究,我了解到go mod download
可以根据go.mod
将Go Modules缓存到本地。
对我来说,go.mod
文件是一个很好的解决方案,因为它指定了确切的模块版本;所以在使用Docker时,缓存会更简单,因为可以重用层,除非go.mod
发生了变化。
我通过运行go mod init github.com/me/myproject
来轻松实现这一点,然后后续的go get
调用会将相关模块添加到go.mod
中。
但是我缺少最后一步,类似于go mod download
但具有与go get
相同的“输出”,它将构建的二进制文件保存到GOBIN
中。
只是为了澄清,我使用的是用Go构建的工具的二进制文件,但我的项目本身不是一个Go应用程序,它只是使用这些工具。
英文:
I have a multi-stage Dockerfile (uisng BuildKit) which contains an initial stage to go get
several tools that I need to use as binaries in a later stage.
The following example is the gist of it:
# syntax = docker/dockerfile:1.0-experimental
# Go build stage
FROM golang:1.14-alpine3.12 AS gobuild
RUN apk add --no-cache git
RUN GO111MODULE=on go get -v github.com/tool1/tool1
RUN GO111MODULE=on go get -v github.com/tool2/tool2
RUN GO111MODULE=on go get -v github.com/tool3/tool3
# ...
# Release stage
FROM base AS release
# Copy Go binaries
COPY --from=gobuild /go/bin/tool1 /usr/local/bin/tool1
COPY --from=gobuild /go/bin/tool2 /usr/local/bin/tool2
COPY --from=gobuild /go/bin/tool3 /usr/local/bin/tool3
# ...
This works well. The only issue I have is that every docker build
requires the Go Modules to be downloaded again, i.e. they aren't cached.
After some research, I read about go mod download
which is meant to cache Go Modules locally according to go.mod
.
The go.mod
file is a good solution for me, in that it states exact module versions; so when using Docker, caching will be much simpler since layers can be re-used unless go.mod
has changed.
I easily achieve this by running go mod init github.com/me/myproject
and then subsequent go get
calls add the relevant modules to go.mod
.
But I am missing the final piece, something similar to go mod download
but with the same "output" as go get
, which saves the built binaries to GOBIN
.
Just to clarify, I am using binaries of tools built with Go, but my project itself isn't a Go app, it only makes use of these tools.
答案1
得分: 0
根据评论中的建议,在我的情况下,使用Go 1.16和go install package@version
是最佳解决方案。
我的Dockerfile现在如下所示:
# syntax = docker/dockerfile:1.0-experimental
# Go build stage
FROM golang:1.16-alpine3.12 AS gobuild
RUN apk add --no-cache git
RUN go install github.com/tool1/tool1@latest
RUN go install github.com/tool2/tool2@latest
RUN go install github.com/tool3/tool3@v1.0.0
# ...
英文:
As suggested in the comments, using Go 1.16 and go install package@version
serves as the best solution in my case.
My Dockerfile now looks like this:
# syntax = docker/dockerfile:1.0-experimental
# Go build stage
FROM golang:1.16-alpine3.12 AS gobuild
RUN apk add --no-cache git
RUN go install github.com/tool1/tool1@latest
RUN go install github.com/tool2/tool2@latest
RUN go install github.com/tool3/tool3@v1.0.0
# ...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论