Go dockerized 构建,缓存依赖拉取层
Go dockerized build, cacheing the dependency pull layer
我正在使用 skaffold
开发一些 kubernetes 服务,但我的周期中最长的步骤之一是拉取容器的所有依赖项。
有没有人对我如何最好地缓存一个层中的所有依赖项有建议?在 docker 容器内构建 go 二进制文件是否有最佳实践?我应该有一个层来做 go get
吗? (另外,我是构建二进制文件的新手,还不知道所有的花里胡哨。)
Go服务习惯用multi-stage build。
这样所有依赖项都已解决并且可执行文件是在构建阶段构建的。最后阶段实际上是 运行 可执行文件。因此,您的最终图像尺寸会更小。虽然,它不会加快依赖项解析阶段。
我同意 Grigoriy Mikhalkin 的观点。关于您的性能改进,我想命名为 Docker Build Enhancements which are based on moby/buildkit。在撰写本文时,这些工具没有正确记录,但通过反复试验,您可能会找到适合自己的解决方案。
使用 buildkit,您可以在 RUN
语句中使用缓存,以减少后续执行的时间。他们也提供 example of Go in their docs。为了让它工作,您必须为 Docker 守护程序和客户端启用实验性功能(在上面的 link 中描述)。
我在谷歌上搜索了更多内容后发现了这篇文章,其中涵盖了整个过程:Using go mod download to speed up Golang Docker builds
技巧的要点是将你的go.mod
和go.sum
文件复制到容器中,然后运行go mod download
下载依赖项,然后在另一个步骤中继续构建。
这是有效的,因为你的 go.mod
和 go.sum
文件 不会 改变,除非你添加更多依赖项。因此,当下一个 RUN
语句发生时,go mod download
docker 知道它可以缓存该层。 (Source)
FROM golang:1.13.9-buster as builder
# Make Build dir
RUN mkdir /build
WORKDIR /build
# Copy golang dependency manifests
COPY go.mod .
COPY go.sum .
# Cache the downloaded dependency in the layer.
RUN go mod download
# add the source code
COPY . .
# Build
RUN go build -o app
# Run
FROM debian:buster-slim
COPY --from=builder /build
WORKDIR /app
CMD ["./app"]
我在将 skaffold
与 kubebuilder
集成时遇到了完全相同的问题,完全解决此问题的想法是:
安装buildkit,例如:brew install buildkit
;
要为本地构建启用 skaffold
,方法如下:
apiVersion: skaffold/v1beta9
kind: Config
build:
local:
useBuildkit: true
useDockerCLI: true
...
- 编辑
Dockerfile
以启用它:
# syntax=docker/dockerfile:experimental
# Build the manager binary
FROM golang:1.12.5 as builder
...
# Build
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -o manager main.go
...
然后第一次它仍然会下载所有依赖项,但之后它会使用缓存,这会大大加快构建过程。
我正在使用 skaffold
开发一些 kubernetes 服务,但我的周期中最长的步骤之一是拉取容器的所有依赖项。
有没有人对我如何最好地缓存一个层中的所有依赖项有建议?在 docker 容器内构建 go 二进制文件是否有最佳实践?我应该有一个层来做 go get
吗? (另外,我是构建二进制文件的新手,还不知道所有的花里胡哨。)
Go服务习惯用multi-stage build。 这样所有依赖项都已解决并且可执行文件是在构建阶段构建的。最后阶段实际上是 运行 可执行文件。因此,您的最终图像尺寸会更小。虽然,它不会加快依赖项解析阶段。
我同意 Grigoriy Mikhalkin 的观点。关于您的性能改进,我想命名为 Docker Build Enhancements which are based on moby/buildkit。在撰写本文时,这些工具没有正确记录,但通过反复试验,您可能会找到适合自己的解决方案。
使用 buildkit,您可以在 RUN
语句中使用缓存,以减少后续执行的时间。他们也提供 example of Go in their docs。为了让它工作,您必须为 Docker 守护程序和客户端启用实验性功能(在上面的 link 中描述)。
我在谷歌上搜索了更多内容后发现了这篇文章,其中涵盖了整个过程:Using go mod download to speed up Golang Docker builds
技巧的要点是将你的go.mod
和go.sum
文件复制到容器中,然后运行go mod download
下载依赖项,然后在另一个步骤中继续构建。
这是有效的,因为你的 go.mod
和 go.sum
文件 不会 改变,除非你添加更多依赖项。因此,当下一个 RUN
语句发生时,go mod download
docker 知道它可以缓存该层。 (Source)
FROM golang:1.13.9-buster as builder
# Make Build dir
RUN mkdir /build
WORKDIR /build
# Copy golang dependency manifests
COPY go.mod .
COPY go.sum .
# Cache the downloaded dependency in the layer.
RUN go mod download
# add the source code
COPY . .
# Build
RUN go build -o app
# Run
FROM debian:buster-slim
COPY --from=builder /build
WORKDIR /app
CMD ["./app"]
我在将 skaffold
与 kubebuilder
集成时遇到了完全相同的问题,完全解决此问题的想法是:
安装buildkit,例如:
brew install buildkit
;要为本地构建启用
skaffold
,方法如下:
apiVersion: skaffold/v1beta9
kind: Config
build:
local:
useBuildkit: true
useDockerCLI: true
...
- 编辑
Dockerfile
以启用它:
# syntax=docker/dockerfile:experimental
# Build the manager binary
FROM golang:1.12.5 as builder
...
# Build
#RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -o manager main.go
...
然后第一次它仍然会下载所有依赖项,但之后它会使用缓存,这会大大加快构建过程。