创建 docker 容器以运行 `go test`,并下载并缓存所有模块依赖项

Joe*_*Joe 6 go docker

我想在需要使用 Docker 的 CI 环境中测试我的 Go 代码。如何创建一个 Docker 映像,该映像具有go.mod已下载和编译的所有依赖项,以便docker run $IMG go test使用缓存的工件?

此图像所需的属性:

  • 该映像仅用于go.mod编译依赖项。我不想使用完整的源代码,因为对源代码的任何更改都会使保存缓存依赖项的 Docker 层无效。

  • docker run $IMG go test ./...不会重新下载或重新编译go.mod.

  • 避免实验性的 Docker 功能。

现有方法

解析 go.mod 并使用 go get

来自https://github.com/golang/go/issues/27719#issuecomment-578246826

这种方法很接近,但GOCACHE在我运行时似乎没有使用go test. 这似乎也会阻塞某些模块路径,例如gopkg.in/DataDog/dd-trace-go.v1

FROM golang:1.13
WORKDIR /src
COPY go.mod ./
RUN set -eu \
  && go mod graph \
  | cut -d '@' -f 1 \
  | cut -d ' ' -f 2 \
  | sort -u \
  | sed -e 's#dd-trace-go.v1#&/ddtrace#' \
  | xargs go get -v
Run Code Online (Sandbox Code Playgroud)
docker run --mount /src:/src $IMG go test ./...
Run Code Online (Sandbox Code Playgroud)

将 DOCKER_BUILDKIT 与挂载缓存一起使用

最初描述于 https://github.com/golang/go/issues/27719#issuecomment-514747274 中。这仅适用于go build. 我不能使用它,go test因为缓存挂载在 RUN 命令之后被卸载,所以它不存在于创建的 Docker 镜像中。

这也取决于实验性 docker 功能。

# syntax = docker/dockerfile:experimental
FROM golang:1.13 as go-builder
ARG VERSION
WORKDIR /src
COPY . /src/
# With a mount cache, Docker will cache the target directories for future
# invocations of this RUN layer. Meaning, once this command is run once, all
# successive calls will use the already downloaded and already compiled assets.
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    go build ./server
Run Code Online (Sandbox Code Playgroud)

Ari*_*ith 1

我经常放在COPY go.modDockerfile 的开头,因为它不会经常更改。

FROM golang:1.14.3 as builder

WORKDIR /app

COPY go.mod .
COPY go.sum .

RUN go mod download

COPY . .
RUN go build -tags netgo -ldflags '-extldflags "-static"' -o app .

FROM centos:7  
WORKDIR /root

COPY --from=builder /app/app .
Run Code Online (Sandbox Code Playgroud)

所以,如果你去mod不改变,该行RUN go mod download只会运行第一次。