GitLab CI 配置文件必须放在项目根目录,命名为 .gitlab-ci.yml;Go 构建需确保有 go.mod 并设置 GO111MODULE=on;部署应使用 SSH_PRIVATE_KEY 变量配合 ssh-agent;编译建议加 -ldflags '-s -w' 和 CGO_ENABLED=0 优化体积与兼容性。

GitLab CI 配置文件写在哪、叫什么名
GitLab CI 的配置必须放在项目根目录下,文件名严格为 .gitlab-ci.yml,少一个点或拼错大小写都会导致流水线不触发。它不是可选配置,而是 GitLab 自动识别的唯一入口。
- 不能叫
gitlab-ci.yaml(后缀必须是yml) - 不能放在
.gitlab/或ci/子目录里(必须根目录) - 如果用了
include:引用外部 yml,被引用文件也需符合 YAML 语法,且路径是相对于项目根目录的
Go 构建阶段为什么总报 go: cannot find main module
这是最常见的失败原因:GitLab Runner 在执行 go build 前没正确初始化 Go 模块环境。默认工作目录是仓库根,但 go mod 可能因缺少 go.mod 或 GOPATH 干扰而失效。
- 确保项目根目录存在
go.mod文件(用go mod init example.com/myapp初始化) - 在
.gitlab-ci.yml的before_script中显式设置GO111MODULE=on - 避免在 CI 中使用
go get安装依赖——改用go mod download,更稳定且可缓存 - 示例片段:
before_script: - export GO111MODULE=on - go mod download
如何安全地把构建产物部署到远程服务器
CI 流水线本身不该持有生产环境密钥,也不能硬编码密码或私钥。GitLab 提供了 CI/CD Variables + SSH_PRIVATE_KEY 变量方案,配合 ssh 和 rsync 实现无密码部署。
- 在 GitLab 项目 Settings → CI/CD → Variables 中添加变量
SSH_PRIVATE_KEY,值为 PEM 格式私钥(注意去掉注释行和空行) - 部署脚本中先用
ssh-agent加载密钥:eval $(ssh-agent -s) echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - mkdir -p ~/.ssh chmod 700 ~/.ssh
- 用
rsync --delete同步二进制文件,比scp更可控;目标路径建议用变量DEPLOY_HOST和DEPLOY_PATH抽离 - 别在
.gitlab-ci.yml里写ssh user@host 'systemctl restart myapp'—— 权限和环境变量可能不一致,改用预置的部署脚本
Go 编译产物体积大、上传慢,怎么优化
默认 go build 生成的二进制含调试信息、符号表,体积常超 20MB,拖慢 CI 时间和制品上传。这不是 bug,是 Go 默认行为。
立即学习“go语言免费学习笔记(深入)”;
- 加
-ldflags '-s -w':去掉符号表(-s)和 DWARF 调试信息(-w),体积通常缩小 50%~70% - 启用
CGO_ENABLED=0:避免动态链接 libc,生成纯静态二进制,提升跨环境兼容性(尤其 Alpine 镜像) - 示例命令:
CGO_ENABLED=0 go build -ldflags '-s -w' -o ./bin/myapp ./cmd/myapp
- 注意:加了
-s -w后,pprof和 panic stack trace 会丢失文件名和行号,仅保留函数名;线上排障需权衡
GitLab CI 的 Go 流水线真正难的不是写对语法,而是让每个环节的环境假设都显式化——比如 Go 版本、模块模式、SSH 密钥加载时机、静态链接是否影响日志上下文。这些细节一旦隐含在某个 Runner 的本地配置里,就很难复现和迁移。










