Woodpecker CI 踩坑记:从搭建到跑通的一次排障

2026-05-23

给 BOM 项目搭 Woodpecker + Gitea CI,踩了几个坑。挑两个最耗时的记一下。


坑一:gRPC 连不上

Woodpecker 的 Server 和 Agent 之间用 gRPC(端口 9000),需要 h2c 协议。最开始想用 Caddy 统一反代所有流量,试了一堆方案都不通:

尝试结果
Caddy 全局 h2c 模式Woodpecker 不支持全量 h2c
按路径分 handle_path /proto.*服务端没开 WOODPECKER_GRPC_H2C=true
加上 H2C 开关内部路由还是不匹配
防火墙放行 9000 端口忘了开
Agent 连公网 IP + 9000能连但频繁掉线

最终方案很粗暴:Web 走 Caddy(8000),gRPC 直连 9000 端口,不经过反向代理。两边都稳定了。


坑二:Go 模块下载被墙

Agent 连上之后 pipeline 能跑了,但 test 一直失败(exit=2)。查下来是 go mod download 卡在 proxy.golang.org — 解析到 Google Cloud IP,国内直连 TLS 握手超时。

试过的路:

  1. HTTP_PROXY — 本机有 ShellCrash 代理(:7890),但从 Docker 容器里连不上。ShellCrash 的 iptables tproxy 规则拦截了 Docker 桥接流量
  2. Docker daemon proxy — 给 dockerd 配了 HTTPS_PROXY,但这只对镜像拉取生效,不影响容器内网络
  3. 本地镜像缓存 — 用 --network host 构建了带全部模块的镜像,但 pipeline 被远程 agent 拾取,找不到这个本地镜像
  4. go mod vendor — vendor 目录 235MB,不想提交

最终方案就一行:

environment:
  GOPROXY: https://goproxy.io,direct

goproxy.io 在国内可以直接访问,不需要 HTTP 代理。换上去之后 go mod download 秒过,pipeline 全线通过。


几个教训

  • Caddy 反代 gRPC 搞不定就直连,别硬扛
  • ShellCrash / Clash 系代理的 iptables 规则会拦截 Docker 桥接流量,容器内别指望 HTTP_PROXY
  • proxy.golang.org 在国内通常不可用,换成 goproxy.io
  • 排查时直接用 API 拿 JSON 比看 UI 更可靠(日志端点可能被反向代理吞掉)
  • golang:1.25-alpine 不存在,Go 从 1.22 起已停发 Alpine 变体
https://blog.logfun.xyz/blog/feed.xml