go111module必须显式设为on,否则docker构建会fallback至gopath模式,导致go build报“no required module provides package”;需在dockerfile开头设env go111module=on,并配合goproxy和goprivate配置确保依赖正确拉取与校验。

GO111MODULE=on 必须显式设置,否则 Docker 构建会 fallback 到 GOPATH
很多人在 Dockerfile 里写 go build 却发现依赖根本没拉、报错 no required module provides package,根本原因就是构建环境里 GO111MODULE 没开。CI 镜像或精简 base 镜像(比如 golang:alpine)默认仍是 auto 或 off,不会自动识别模块。
必须在 Dockerfile 开头就设死:
ENV GO111MODULE=on
别指望靠 go mod init 触发自动启用——auto 模式在 /tmp、/app 这类非 GOPATH 路径下直接失效,而容器里几乎全是这种路径。
常见错误:
- 只在本地 shell 里
go env -w GO111MODULE=on,但没写进 Dockerfile - 用
go mod init后不验证go env GO111MODULE,误以为已生效 - 在 multi-stage 构建的 builder 阶段漏设,导致
go mod download失败
go mod download 要放在 COPY 代码之前,否则缓存失效
Docker 分层缓存只认指令内容和上一层哈希。如果把 COPY . . 放在 go mod download 前面,每次改代码都会让后续所有层失效,包括依赖下载——等于每次构建都重拉一遍模块。
正确顺序是:
WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go build -o myapp .
注意两点:
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
-
go.sum必须和go.mod一起COPY,否则go mod download会拒绝执行(校验失败) - 不要用
go mod tidy替代go mod download:前者会扫描源码、触发 import 解析,而源码还没 copy,必然失败 - 如果项目用了
replace指向本地路径(如./local-utils),go mod download会跳过它——这是正常行为,但得确保该路径在构建上下文里存在
私有模块路径不匹配会导致 checksum mismatch
容器里跑 go build 报 verifying github.com/yourorg/lib@v0.1.0: checksum mismatch?八成是 go.mod 里的 module 声明和 Git 仓库实际路径对不上。
比如代码托管在 git.internal.company.com/team/project,但 go.mod 写的是 module project 或 module internal/project,Go 就会按错误路径去算 checksum,自然校验不过。
修复方法:
- 确认
go.mod第一行module完全匹配仓库根 URL 路径(不含协议、端口、.git 后缀) - 私有域名必须加进
GOPRIVATE:在 Dockerfile 里加ENV GOPRIVATE=git.internal.company.com,否则 Go 仍会走GOPROXY去查,返回 401 或 404 - 若用
replace指向内部 Git 仓库,路径必须用完整 URL(如replace git.internal.company.com/team/lib => git.internal.company.com/team/lib v0.2.0),不能用相对路径
vendor 目录在容器里反而破坏缓存和安全性
有人为了“离线构建”把 vendor/ 提交进 Git 并 COPY 进镜像,结果发现构建变慢、镜像体积暴涨,还埋下安全风险。
原因很直接:
-
vendor/一旦存在,go mod download和go mod tidy默认跳过它,导致go.sum不更新,新漏洞依赖无法被检测 -
COPY vendor/ ./让 Docker 缓存极易失效——只要任意一个依赖文件变动,整个 vendor 层就废了 - 多阶段构建中,builder 阶段若用了 vendor,最终二进制里仍可能残留调试符号或未清理的测试依赖
真正需要 vendor 的场景极少,比如完全断网的生产环境。绝大多数情况,删掉 vendor/,靠 go mod download + GOPROXY 更可靠、更小、更安全。
如果非要用,务必加 -v 参数清理:go mod vendor -v,且在 Dockerfile 中显式 RUN go mod vendor -v,避免 COPY 过时的 vendor。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










