【发布时间】:2021-10-14 05:47:48
【问题描述】:
在构建 Docker 镜像时,我知道我们可以添加一个层来缓存依赖项。但是需要建立依赖关系。这一步相当耗时,在我的机器上单独构建 sqlite3 大约需要 30 秒。
我也知道我可以使用go build github.com/mattn/go-sqlite3 来构建特定的依赖项,但是有没有办法预先构建go.mod 中的所有依赖项列表?
我发现了关于这个here的相同问题,但没有答案。
【问题讨论】:
在构建 Docker 镜像时,我知道我们可以添加一个层来缓存依赖项。但是需要建立依赖关系。这一步相当耗时,在我的机器上单独构建 sqlite3 大约需要 30 秒。
我也知道我可以使用go build github.com/mattn/go-sqlite3 来构建特定的依赖项,但是有没有办法预先构建go.mod 中的所有依赖项列表?
我发现了关于这个here的相同问题,但没有答案。
【问题讨论】:
Docker 提供了关于这个确切主题 here 的文档。建议是像这样构建您的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 中测试,但应该可以工作。不过,它可能会进一步优化,或修改为在更有限的构建环境中工作
RUN go mod download && go list -f '{{ join .Deps "\n" }}' ./... | sort -u | grep -v '<your package import path>' | xargs go build
【讨论】: