如何在Docker中预编译Go应用依赖包以加快主程序构建速度
问题原因
你当前使用的go build /root/go/pkg/...命令不符合Go模块模式的路径规则,Go在启用模块管理时,仅允许识别当前模块根目录(也就是你go.mod所在的/gadic目录)下的代码路径,/root/go/pkg属于GOPATH全局缓存目录,不在当前模块的路径范围内,因此触发报错。
解决方案
按以下步骤修改Dockerfile即可实现依赖预编译,和业务代码编译分层:
- 除了
go.mod之外,还要把go.sum也提前拷贝到镜像的工作目录,用于校验依赖版本完整性 - 把报错的
RUN go build /root/go/pkg/...替换为RUN go build -mod=readonly all,该命令会预编译当前模块声明的所有依赖包,不需要提前拷贝业务源代码 - 后续再拷贝业务代码编译main.go时,就可以直接复用之前预编译好的依赖缓存,大幅提升编译速度
修改后的完整Dockerfile示例:
FROM ubuntu:focal # ... 此处省略安装Go及其他所需二进制文件的RUN命令 ENV GOPATH=/root/go WORKDIR /gadic # 先拷贝依赖声明文件 COPY go.mod go.sum ./ # 下载所有依赖到本地缓存 RUN go mod download # 预编译所有依赖包 RUN go build -mod=readonly all # 再拷贝业务源代码 COPY src src # 此时编译main.go会直接复用已预编译的依赖,无需重新编译依赖 RUN go build path/to/main.go
可选优化建议
- 推荐直接使用官方
golang:x.y镜像作为构建阶段基础镜像,不需要自行安装Go环境,减少镜像配置复杂度 - 可以搭配多阶段构建,把最终编译出的可执行文件拷贝到空镜像或者ubuntu等运行时镜像中,大幅减小最终镜像体积
- 如果不需要cgo依赖,可以在构建时加上
CGO_ENABLED=0参数,编译出静态可执行文件,更方便在轻量镜像中运行
内容的提问来源于stack exchange,提问作者Paymahn Moghadasian
相关产品推荐
相关产品推荐

