英文:
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 && go list -f '{{ join .Deps "\n" }}' ./... | sort -u | grep -v '<your package import path>' | xargs go build
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论