如何通过go.mod将编译好的Go模块输出到GOBIN以实现Docker缓存
实现方案
前置准备
你本地已经完成go mod init初始化,接下来直接执行所有需要的工具的go get命令,确认生成的go.mod、go.sum文件已经正确记录了所有工具的依赖版本,将这两个文件放到Docker构建的上下文根目录中。
优化后的Dockerfile编写
核心逻辑是拆分镜像层,把可缓存的依赖下载步骤和编译步骤分开,用go mod download做缓存,go install生成二进制,调整后的gobuild阶段示例如下:
# syntax = docker/dockerfile:1.0-experimental # Go build stage FROM golang:1.14-alpine3.12 AS gobuild RUN apk add --no-cache git # 先单独复制go.mod和go.sum,只要这两个文件不变,后续层直接复用缓存 COPY go.mod go.sum ./ # 下载所有依赖模块,这一层可长期缓存 # 可选优化:加BuildKit缓存挂载,即使go.mod变动也能复用已下载的模块 RUN --mount=type=cache,target=/go/pkg/mod \ GO111MODULE=on go mod download # 编译所有工具的二进制到GOBIN路径,不会重复下载依赖 RUN GO111MODULE=on go install github.com/tool1/tool1 RUN GO111MODULE=on go install github.com/tool2/tool2 RUN GO111MODULE=on go install github.com/tool3/tool3 # 后续release阶段和原有逻辑完全一致,不需要修改
原理说明
- Docker镜像层缓存机制会检查
COPY go.mod go.sum这一步的文件是否变动,只要没有修改就会直接复用之前的go mod download层,不会重新下载依赖 go install命令和你之前用的go get生成二进制的效果完全一致,都会把编译好的可执行文件输出到/go/bin目录下,后续copy逻辑不需要任何调整- 如果开启了BuildKit的缓存挂载,即使
go.mod发生了修改,也会复用本地已经缓存过的Go模块,不需要全量重新下载,构建速度更快
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

