feat: Wormhole 内网穿透与反向代理网关
CI / docker (push) Successful in 1m58s

Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。
Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-15 04:46:59 +00:00
committed by renjue
commit 0d84b07f68
111 changed files with 15770 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
# Gitea Actions CI 模板(Go + Vue
复制整个 `.gitea/` 目录到新仓库即可启用 CI:**可选 go test** + **Docker 构建/推送**Go 编译与 Vue 构建在 Dockerfile 内完成)。
## 项目约定
| 路径 | 说明 |
|------|------|
| `go.mod` | 仓库根目录 |
| `Dockerfile` | 仓库根目录,多阶段构建(含前端 `web/` |
| `web/` | 可选;由 Dockerfile 内 `npm run build` 处理,CI 不再单独构建 |
## Dockerfile 要求
工作流的 **Build image** 步骤在仓库根目录(或 Variable `DOCKERFILE` 指定路径)执行 `docker buildx build`**不会**在 CI 里单独装 Node / 跑 `npm`。因此 Dockerfile 必须能独立完成构建与(运行时)启动。
### 基本要求
| 项 | 要求 |
|----|------|
| 位置 | 默认仓库根目录 `Dockerfile`;其他路径用 Variable `DOCKERFILE` |
| 构建上下文 | 仓库根目录 `.`(整个仓库会被 `COPY` 进镜像) |
| Go 版本 | `go.mod``go` 行与 `golang` 基础镜像大版本一致 |
| 多架构 | `go build` 须使用 `GOARCH="$TARGETARCH"`buildx 注入);推荐 `CGO_ENABLED=0` |
| Go 模块代理 | **必须**在镜像内显式设置 `GOPROXY` / `GOSUMDB`(见下);容器内不会自动读取 `go.env` |
| 基础镜像加速 | 支持构建参数 `IMAGE_PREFIX`CI 默认 `docker.1panel.live/library/` |
| 前端(可选) | 存在 `web/` 时在 Dockerfile 内完成 `npm ci` + `npm run build` |
### CI 自动传入的构建参数
| 参数 | 默认 | 说明 |
|------|------|------|
| `IMAGE_PREFIX` | `docker.1panel.live/library/` | 基础镜像前缀;`hub` 表示 Docker Hub |
| `GOPROXY` | `https://goproxy.cn,direct` | 与 workflow / Variable 一致 |
| `GOSUMDB` | `sum.golang.google.cn` | checksum 数据库 |
buildx 还会注入 `TARGETARCH``BUILDPLATFORM` 等,无需在 workflow 里写。
### 推荐:Go + Vue 多阶段模板
```dockerfile
# syntax=docker/dockerfile:1
ARG IMAGE_PREFIX=
# 1) 前端(无 web/ 时可删整个 stage,并去掉 go-builder 里 COPY dist
FROM --platform=$BUILDPLATFORM ${IMAGE_PREFIX}node:20-alpine AS web-builder
WORKDIR /src/web
COPY web/package.json web/package-lock.json web/.npmrc ./
RUN npm ci
COPY web/ ./
RUN npm run build
# 2) Go 编译
FROM --platform=$BUILDPLATFORM ${IMAGE_PREFIX}golang:1.25-alpine AS go-builder
ARG TARGETARCH
ARG GOPROXY=https://goproxy.cn,direct
ARG GOSUMDB=sum.golang.google.cn
ENV GOPROXY=${GOPROXY} GOSUMDB=${GOSUMDB}
WORKDIR /src
COPY go.mod go.sum ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download
COPY cmd/ ./cmd/
COPY internal/ ./internal/
# 若静态资源嵌入 GoCOPY --from=web-builder /src/web/dist/ ./path/to/static/
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux GOARCH="$TARGETARCH" \
go build -ldflags="-w -s" -o /app ./cmd/yourapp
# 3) 运行镜像
FROM ${IMAGE_PREFIX}alpine:3.20
RUN apk add --no-cache ca-certificates tzdata
COPY --from=go-builder /app /usr/local/bin/yourapp
ENTRYPOINT ["/usr/local/bin/yourapp"]
```
按项目调整:`./cmd/yourapp`、静态资源路径、运行用户、`EXPOSE` / `VOLUME` 等。
### 仅 Go(无前端)
删除 `web-builder` stage`go-builder` 中不要 `COPY` 前端产物;其余 `GOPROXY` / `TARGETARCH` / `IMAGE_PREFIX` 要求相同。
### 前端 npm 源(国内)
`web/.npmrc` 配置 registry,并在 Dockerfile 里与 `package.json` 一并 `COPY`
```ini
registry=https://registry.npmmirror.com
```
### 本地验证(与 CI 一致)
```bash
docker buildx build --platform linux/amd64 \
--build-arg IMAGE_PREFIX=docker.1panel.live/library/ \
--build-arg GOPROXY=https://goproxy.cn,direct \
-f Dockerfile -t myapp:test .
```
### 常见 Dockerfile 构建错误
| 报错 | 原因 | 处理 |
|------|------|------|
| `proxy.golang.org` timeout | 镜像内未设 `ENV GOPROXY` | go-builder 阶段加 `ARG`/`ENV GOPROXY` |
| `node` / Vite 版本不符 | 基础镜像 Node 过旧 | 使用 `node:20-alpine` 及以上 |
| 某架构 build 失败 | 未使用 `TARGETARCH` | `GOARCH="$TARGETARCH"` |
| 拉基础镜像 timeout | Hub 不可达 | `--build-arg IMAGE_PREFIX=docker.1panel.live/library/` 或 1Panel 配镜像加速 |
## 一次性配置
1. **Runner**:部署 act_runner,标签含 `ubuntu-latest`,并挂载 `docker.sock`(见 [act-runner/README.md](act-runner/README.md))。
2. **Secret**:仓库 Settings → Actions → Secrets,添加 `REGISTRY_TOKEN`PAT`write:package` 权限)。
3. **Variable(推荐)**:若 runner 与 Gitea 同机、或 `gitea.server_url` 为内网地址,必须设置 `REGISTRY=你的公网域名`(如 `git.example.com`**不要**填 `172.17.0.1:13827`)。
4. **Gitea Registry**:服务端 `[packages] ENABLED = true``ROOT_URL` 正确;穿透场景建议 `PUBLIC_URL_DETECTION = never`Gitea 1.26+)。
`REGISTRY` 未设置时,会从 `GITEA_ROOT_URL``gitea.server_url` 推断;均为内网地址时 workflow 会提前失败并提示。
## 可选 Variables
仓库 Settings → Actions → Variables(留空则用默认值):
| 变量 | 默认 | 说明 |
|------|------|------|
| `REGISTRY` | 见下方推断顺序 | **公网** Registry 主机名,如 `git.example.com`(勿用内网 IP:13827 |
| `GITEA_ROOT_URL` | (空) | 当 `gitea.server_url` 为内网时,可设 `https://git.example.com/` |
| `IMAGE_NAME` | 仓库名小写 | 镜像名,非 owner/repo 全路径 |
| `DOCKERFILE` | `Dockerfile` | Dockerfile 路径 |
| `DOCKER_PLATFORMS` | `linux/amd64,linux/arm64` | push 时 buildx 平台 |
| `GO_TEST_SCOPE` | `./...` | `go test` 包路径 |
| `RUN_GO_TEST` | (空,即运行) | 设 `false` 跳过 go test,仅 Docker 构建 |
| `DOCKER_IMAGE_PREFIX` | `1panel` | 基础镜像前缀;可选 `hub` / `daocloud` |
| `GOPROXY` | `https://goproxy.cn,direct` | Go 模块代理 |
| `GOSUMDB` | `sum.golang.google.cn` | Go checksum 数据库 |
## 触发与镜像 tag
- **pull_request**go test(可关)+ 单架构 `docker build` 验证(不推送)
- **push main/master**go test + 多架构构建并推送 `:latest``:sha-xxxxxxx`
- **push tag v\***:额外推送 `:v1.2.3`
示例(仓库 `rose_cat707/Prism`Gitea 在 `git.example.com`):
```text
git.example.com/rose_cat707/prism:latest
git.example.com/rose_cat707/prism:sha-35b3b48
```
## 目录结构
```text
.gitea/
├── README.md # 本文件
├── workflows/
│ └── ci.yml # 主工作流
└── act-runner/ # runner 部署参考(可选)
├── README.md
├── config.yaml
├── docker-compose.yml
└── .env.example
```
## 本地验证 Registry
```bash
host=$(echo "https://你的-gitea-地址/" | sed -e 's|^https://||' -e 's|/.*||')
curl -s -D - "https://${host}/v2/" -o /dev/null | grep -i www-authenticate
docker pull "${host}/owner/image:latest" # 公开 Registry 无需 login
```
推送镜像(CI)仍需仓库 Secret `REGISTRY_TOKEN``write:package`)。仅拉取公开包不需要登录。
`realm` 应指向公网 Gitea 域名,而非 `127.0.0.1`
## 常见 Registry 错误
| 报错 | 原因 | 处理 |
|------|------|------|
| `Get "https://172.17.0.1:13827/v2/"` HTTP/HTTPS | Variable `REGISTRY``gitea.server_url` 为内网地址 | 设 `REGISTRY=git.example.com` |
| token 指向 `127.0.0.1` | Gitea `realm` 配置错误 | `PUBLIC_URL_DETECTION=never` + 正确 `ROOT_URL` |