根本原因是 go.mod 未被识别或工作目录错误;需确保在项目根目录执行、go.mod 已提交、go 版本一致、避免 before_script 中 go get;交叉编译后勿在异构 runner 上直接运行;docker 推送需正确配置凭证;部署命令须非阻塞并校验服务状态。

Go build 在 CI 中总报 cannot find module
根本原因是 go.mod 没被正确识别或工作目录不对,不是 GOPATH 问题(Go 1.16+ 默认 module 模式)。GitLab Runner 默认在项目根目录启动,但如果你用了 before_script 切目录、或 include 了子模块,go build 就会找不到模块。
- 确保
.gitlab-ci.yml中所有script步骤都在项目根目录执行,显式加cd $CI_PROJECT_DIR最稳妥 - 检查
go.mod文件是否真的在 Git 提交里(别 .gitignore 误删了) - Go 版本要和本地一致,用
golang:1.21-alpine这类镜像时,确认它含go mod支持(Alpine 的apk add go有时版本滞后) - 避免在
before_script里运行go get—— 它会改写go.mod,导致 CI 和本地不一致
交叉编译 Linux 二进制却在 runner 上跑失败
GOOS=linux GOARCH=amd64 go build 确实能生成 Linux 可执行文件,但如果你用的是 docker:dind 或自建 macOS runner,build 后直接 ./myapp 会报错:不是可执行格式(Exec format error)—— 因为 runner 系统和目标平台不匹配,不是编译错了,是误执行了。
- 只在
build阶段做交叉编译,不要在 build job 里./myapp测试 - 测试必须放在对应平台的 job 里,比如用
image: alpine:latestjob 来chmod +x并运行 - 如果要用 Docker 打包,记得
FROM scratch或FROM alpine,别用FROM golang做最终镜像(体积大、有安全隐患) -
CGO_ENABLED=0必须加,否则静态链接失败,部署到 Alpine 会缺 libc
GitLab CI 推送 Docker 镜像被 denied: requested access to the resource is denied
这是权限问题,不是网络或镜像名写错。GitLab 内置的 $CI_REGISTRY_USER 和 $CI_REGISTRY_PASSWORD 只对当前项目的 registry 有效;如果你推送到第三方仓库(如 Docker Hub、ECR),默认凭证不生效。
- 推 Docker Hub:在项目 Settings → CI/CD → Variables 里手动添加
DOCKER_HUB_USERNAME和DOCKER_HUB_TOKEN(用个人访问令牌,不是密码) - 推 AWS ECR:先在 job 里用
aws ecr get-login-password获取 token,再docker login,不能复用 GitLab 的变量 - 镜像 tag 别硬写
latest,用$CI_COMMIT_TAG或$CI_COMMIT_SHORT_SHA,否则多个 pipeline 会覆盖同一 tag -
docker push前务必docker images确认镜像存在且 tag 正确,CI 日志里看不到终端回显,容易误以为 build 成功就一定有镜像
部署阶段卡住或超时,但日志没报错
常见于用 ssh 或 rsync 部署到远程服务器时,连接未关闭、后台进程未退出,导致 job 一直等待。GitLab CI 不支持交互式 shell,所有命令必须非阻塞、自动退出。
立即学习“go语言免费学习笔记(深入)”;
- SSH 命令末尾加
&& exit 0,避免因 shell 登录态残留挂起 - 用
rsync --rsh="ssh -o ConnectTimeout=10"显式设超时,别依赖默认值 - 如果部署脚本里有
systemctl start myapp,后面必须跟systemctl is-active --quiet myapp做状态校验,否则服务启动失败也不会暴露 - 避免在部署 job 里用
sleep等待服务就绪——应该用curl -f http://localhost:8080/health这类主动探测
最麻烦的其实是 Go 的 net/http.Server 默认不响应 SIGTERM,容器里 kill 后进程还在,下次部署就端口冲突。得自己加 signal.Notify 处理退出,这点很容易被忽略。










