Go dockerized build, cacheing the dependency pull layer

。_饼干妹妹 提交于 2021-01-07 04:50:46

问题


I'm having a ripping good time using skaffold to develop some kubernetes services, but one of the longest steps in my cycle is pulling all the dependencies for the container.

Does anyone have recommendations on how I can best cache all the dependencies in a layer? Are there best practices with building go binaries inside docker containers? Should I have a layer where I do a go get? (Also I'm a novice building go binaries, don't know all the bells and whistles yet.)


回答1:


I agree with Grigoriy Mikhalkin. Regarding your performance improvements, I want to name the Docker Build Enhancements which are based on moby/buildkit. At the time of writing, the tools aren't properly documented, but with some trial and error, you might find your solution.

Using buildkit, you can use a cache in your RUN statements in order to reduce the time of subsequent executions. They provide an example of Go in their docs, as well. In order to have it work, you have to enable the experimental features for both the Docker daemon and client (described on the link above).




回答2:


I encountered exactly the same issue while integrating skaffold with kubebuilder and the idea to completely resolve this issue was:

  1. To install buildkit, for example: brew install buildkit;

  2. To enable skaffold for local build by having something like this:

apiVersion: skaffold/v1beta9
kind: Config
build:
  local:
    useBuildkit: true
    useDockerCLI: true
...
  1. Edit the Dockerfile to enable it:
# 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
...

Then at first time it will still download every dependency but afterwards it will use the cache, which dramatically speeds up the build process.




回答3:


It's customary to use multi-stage build for go services. So that all dependencies resolved and executable is built at build stage. And final stage is actually running executable. As a result, your final image will be more slim in size. Although, it's not gonna speed up dependency resolution stage.




回答4:


I found this article after googling some more which covers the process: Using go mod download to speed up Golang Docker builds

The gist of the trick is to copy your go.mod and go.sum files into the container, then run go mod download to download dependencies, and then in another step continue with your build.

This works because your the go.mod and go.sum files do not change unless you add more dependencies. So, when the next RUN statement happens which is the go mod download docker knows that that it can cache this layer. (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"]


来源:https://stackoverflow.com/questions/61083819/go-dockerized-build-cacheing-the-dependency-pull-layer

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!