如何预先构建所有所需的模块并将它们缓存起来?

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

How to pre-build all required modules and cache them

问题

在构建 Docker 镜像时,我知道我们可以添加一个层来缓存依赖项。但是依赖项需要被构建。这一步非常耗时,在我的机器上,仅构建 sqlite3 就需要大约 30 秒。

我也知道可以使用 go build github.com/mattn/go-sqlite3 来构建特定的依赖项,但是否有办法预先构建 go.mod 中列出的所有依赖项呢?

我在这里找到了同样的问题链接,但是没有答案。

英文:

When buliding a Docker image, I know we can add a layer to cache dependencies. But the dependency needs to be built. This step is quite time-consuming, on my machine it takes about 30 seconds to build sqlite3 alone.

I also know I can use go build github.com/mattn/go-sqlite3 to build a specific dependency, but is there any way to pre-build all the dependencies list in go.mod?

I found the same question about this here, but there is no answer.

答案1

得分: 5

Docker在这个确切的主题上提供了文档,在这里。建议按照以下方式组织你的Dockerfile

FROM --platform=${BUILDPLATFORM} docker.io/golang:1.16.7-alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
ENV CGO_ENABLED=0
COPY go.* .
RUN go mod download
COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build \
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /out/example .

FROM scratch
COPY --from=build /out/example /

其中很多都是样板代码,如果你只构建单个架构,可以删除这些部分;与缓存相关的部分只有:

FROM docker.io/golang:1.16.7-alpine AS build
WORKDIR /src
COPY go.* .
RUN go mod download
COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build go build -o /out/example .

FROM scratch
COPY --from=build /out/example /

这会在/root/.cache/go-build上挂载一个缓存目录,这是go构建缓存的默认位置。第一次构建镜像时,它会填充这个缓存。后续的构建将重用缓存文件。

为了使其工作,你必须使用DOCKER_BUILDKIT=1进行构建,例如:

DOCKER_BUILDKIT=1 docker build -t myimage .

或者使用docker buildx

docker buildx build -t myimage .

我在本地测试过,似乎按预期工作(我已经验证了在第一次构建之外的构建中,在运行go build之前,go-build缓存目录已经填充)。

英文:

Docker provides documentation on this exact topic here. The suggestion is to structure your Dockerfile like this:

FROM --platform=${BUILDPLATFORM} docker.io/golang:1.16.7-alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
ENV CGO_ENABLED=0
COPY go.* .
RUN go mod download
COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build \
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o /out/example .

FROM scratch
COPY --from=build /out/example /

A lot of that is boilerplate you can remove if you're only building for a single architecture; the parts related to caching are really only:

FROM docker.io/golang:1.16.7-alpine AS build
WORKDIR /src
COPY go.* .
RUN go mod download
COPY . .
RUN --mount=type=cache,target=/root/.cache/go-build go build -o /out/example .

FROM scratch
COPY --from=build /out/example /

This mounts a cache directory on /root/.cache/go-build, which is the default location for the go build cache. The first time you build your image it will populate this cache. Subsequent builds will re-use the cached files.

For this to work, you must build with DOCKER_BUILDKIT=1, i.e.:

DOCKER_BUILDKIT=1 docker build -t myimage .

Or use docker buildx:

docker buildx build -t myimage .

I have tested this out locally and it seems to work as intended (I have verified that in builds other than the first one, the go-build cache directory is populated prior to running go build).

答案2

得分: -1

这在Docker中没有经过测试,但应该可以工作。它可能可以进一步优化,或者修改以在更受限制的构建环境中工作。

RUN go mod download && go list -f '{{ join .Deps "\n" }}' ./... | sort -u | grep -v '<your package import path>' | xargs go build
英文:

This isn't tested within Docker, but should work. It can likely be optimized further, though, or modified to work in more limited build environments

RUN go mod download &amp;&amp; go list -f &#39;{{ join .Deps &quot;\n&quot; }}&#39; ./... | sort -u | grep -v &#39;&lt;your package import path&gt;&#39; | xargs go build

huangapple
  • 本文由 发表于 2021年8月11日 00:40:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/68730600.html
匿名

发表评论

匿名网友

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

确定