From 570a6dddad1ecc168736297d5d8a8a07ab5b886b Mon Sep 17 00:00:00 2001 From: gg949 Date: Sun, 20 Sep 2026 21:52:20 +0800 Subject: [PATCH] update --- .github/workflows/docker-publish.yml | 93 ++++++++++++++++++++++++++++ Dockerfile | 30 +++++++++ README.md | 17 +++++ docker-compose.yml | 23 +++++++ docker-entrypoint.sh | 62 +++++++++++++++++++ docker.md | 70 +++++++++++++++++++++ 6 files changed, 295 insertions(+) create mode 100644 .github/workflows/docker-publish.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 docker-entrypoint.sh create mode 100644 docker.md diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..2c72da5 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,93 @@ +name: Build and Publish Docker Image + +# 探针 Docker 镜像(Docker Hub 不需要——直接发 GHCR,与面板镜像同一 registry) +# 触发方式:发 Release 自动构建(tag 即版本号)+ 手动触发 +on: + release: + types: [published] + workflow_dispatch: + inputs: + version: + description: '镜像标签(例如 v1.0.17 或 latest)' + required: true + default: latest + +env: + IMAGE: ghcr.io/gg949/cfsm-agent + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Resolve version + id: vars + run: | + if [ "${{ github.event_name }}" = "release" ]; then + VERSION="${{ github.event.release.tag_name }}" + else + VERSION="${{ github.event.inputs.version }}" + fi + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "构建版本: ${VERSION}" + + - name: Build binaries (linux only) + env: + VERSION: ${{ steps.vars.outputs.version }} + run: | + set -euo pipefail + mkdir -p dist + LDFLAGS="-s -w -X main.version=${VERSION}" + build_one() { + goos="$1"; goarch="$2" + output="dist/cf-probe-${goos}-${goarch}" + echo "Building ${goos}/${goarch} -> ${output}" + GOOS="${goos}" GOARCH="${goarch}" CGO_ENABLED=0 \ + go build -trimpath -ldflags="${LDFLAGS}" -o "${output}" ./cmd/cf-probe + } + build_one linux amd64 + build_one linux arm64 + ls -lh dist/ + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push (amd64 + arm64) + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + provenance: false + tags: | + ${{ env.IMAGE }}:${{ steps.vars.outputs.version }} + ${{ env.IMAGE }}:latest + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Verify manifest + run: | + docker buildx imagetools inspect "${{ env.IMAGE }}:${{ steps.vars.outputs.version }}" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3c9208e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# syntax=docker/dockerfile:1 +# ────────────────────────────────────────────────────────────── +# ProbeDeck Go 探针(cf-probe)Docker 镜像 +# 用法: +# docker run -d --name cf-probe --restart unless-stopped \ +# -e SERVER_ID=<服务器ID> -e SECRET=<密钥> -e WORKER_URL=https://<面板地址>/update \ +# -v /opt/cf-probe:/etc/cf-probe ghcr.io/gg949/cfsm-agent:latest +# 升级 = 重新拉镜像重建容器(容器内禁用自更新,见 entrypoint 说明)。 +# ────────────────────────────────────────────────────────────── +FROM alpine:3.21 + +# ca-certificates:HTTPS 上报/更新检查需要;tzdata:流量重置日按本地时区计算 +RUN apk add --no-cache ca-certificates tzdata + +WORKDIR /app + +# buildx 构建时自动填充 +ARG TARGETOS +ARG TARGETARCH + +COPY --chmod=755 docker-entrypoint.sh /app/docker-entrypoint.sh +COPY cf-probe-${TARGETOS}-${TARGETARCH} /app/cf-probe + +# 配置目录:探针的远程配置下发会写回 config.conf,必须可写 → 建议挂 volume +ENV CF_PROBE_CONFIG_DIR=/etc/cf-probe +VOLUME ["/etc/cf-probe"] + +EXPOSE 17986 + +ENTRYPOINT ["/app/docker-entrypoint.sh"] diff --git a/README.md b/README.md index c137f66..8beeff9 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,23 @@ PowerShell -ExecutionPolicy Bypass -File $script uninstall 卸载会清理当前 Go 版默认安装创建的固定位置和自启动项,不处理旧脚本或手动放置到其他路径的文件。 +## Docker 安装 + +适合 Unraid、群晖 Container Manager、Portainer 等 Docker 环境(不需要 systemd)。镜像:`ghcr.io/gg949/cfsm-agent`(支持 amd64 / arm64)。 + +```bash +docker run -d \ + --name cf-probe \ + --restart unless-stopped \ + -e SERVER_ID=<服务器ID> \ + -e SECRET=<服务器密钥> \ + -e WORKER_URL=https://<面板地址>/update \ + -v /opt/cf-probe:/etc/cf-probe \ + ghcr.io/gg949/cfsm-agent:latest +``` + +三项环境变量必填(面板「服务器」页添加服务器后获取);可选变量、数据持久化、升级方式与 Unraid 模板要点见 [docker.md](docker.md)。 + ## 上报数据说明 Agent 优先使用 WebSocket 上报,并保留旧版 `POST` fallback。配置中的 `WORKER_URL` 仍填写 HTTP(S) 上报地址,例如 `https://example.com/update`;Agent 会把 `https://` 转为 `wss://`、把 `http://` 转为 `ws://`,路径和查询参数保持不变。WebSocket 握手使用标准 `GET + Upgrade`。 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1449214 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +# ProbeDeck 探针 Docker 部署示例 +# 用法:把 <服务器ID>/<服务器密钥>/<面板地址> 换成面板里实际的值后 +# docker compose up -d +services: + cf-probe: + image: ghcr.io/gg949/cfsm-agent:latest + container_name: cf-probe + restart: unless-stopped + environment: + # ── 必填 ── + SERVER_ID: "<服务器ID>" + SECRET: "<服务器密钥>" + WORKER_URL: "https://<面板地址>/update" + # ── 可选 ── + # REPORT_INTERVAL: "60" + # COLLECT_INTERVAL: "0" + # CONNECTION_MODE: "auto" + # PING_MODE: "tcp" + # RESET_DAY: "1" + # INTERFACE: "" + # DEBUG: "0" + volumes: + - ./data:/etc/cf-probe diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..5e0945e --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# ────────────────────────────────────────────────────────────── +# ProbeDeck 探针容器入口 +# • 用环境变量生成/更新 config.conf(面板下发的配置会写回同一文件, +# 所以必须放在可持久化的 volume 上) +# • 不写 AUTO_UPDATE 字段 → 容器内自更新默认关闭 +# (容器升级 = 重新拉镜像,不该由进程自己替换二进制) +# • 日志直接走 stdout/stderr,docker logs 即可查看 +# ────────────────────────────────────────────────────────────── +set -eu + +CONFIG_DIR="${CF_PROBE_CONFIG_DIR:-/etc/cf-probe}" +CONFIG_FILE="${CONFIG_DIR}/config.conf" + +: "${SERVER_ID:?请设置 SERVER_ID 环境变量(面板里的服务器 ID)}" +: "${SECRET:?请设置 SECRET 环境变量(面板里的服务器密钥)}" +: "${WORKER_URL:?请设置 WORKER_URL 环境变量(面板上报地址,例如 https://example.com/update)}" + +mkdir -p "${CONFIG_DIR}" + +# ── 生成配置(KV 格式,与 install.sh 写盘格式一致)──────────────── +# 已存在的文件保留(面板远程下发的节点/间隔等改动都在里面), +# 仅当三项必填缺失时才初始化——避免重建容器丢失面板侧配置。 +if [ ! -s "${CONFIG_FILE}" ]; then + cat > "${CONFIG_FILE}" </dev/null; then + sed -i "s|^${key}=.*|${key}=\"${value}\"|" "${CONFIG_FILE}" + else + printf '%s="%s"\n' "${key}" "${value}" >> "${CONFIG_FILE}" + fi +} +update_field SERVER_ID "${SERVER_ID}" +update_field SECRET "${SECRET}" +update_field WORKER_URL "${WORKER_URL}" + +# 容器内禁用自更新:删掉历史遗留的 AUTO_UPDATE 字段 +if grep -q '^AUTO_UPDATE=' "${CONFIG_FILE}" 2>/dev/null; then + sed -i '/^AUTO_UPDATE=/d' "${CONFIG_FILE}" +fi + +DEBUG_FLAG="-debug=0" +if [ "${DEBUG:-0}" = "1" ]; then + DEBUG_FLAG="-debug=1" +fi + +echo "[entrypoint] 使用配置文件 ${CONFIG_FILE}(SERVER_ID=${SERVER_ID})" +exec /app/cf-probe run -config "${CONFIG_FILE}" ${DEBUG_FLAG} diff --git a/docker.md b/docker.md new file mode 100644 index 0000000..0354a49 --- /dev/null +++ b/docker.md @@ -0,0 +1,70 @@ +# Docker 部署(Unraid / 群晖 / 任意 Docker 环境) + +不想用安装脚本(systemd)的话,可以用 Docker 跑探针,适合 Unraid、群晖 Container Manager、Portainer 等环境。 + +## 快速开始 + +```bash +docker run -d \ + --name cf-probe \ + --restart unless-stopped \ + -e SERVER_ID=<服务器ID> \ + -e SECRET=<服务器密钥> \ + -e WORKER_URL=https://<面板地址>/update \ + -v /opt/cf-probe:/etc/cf-probe \ + ghcr.io/gg949/cfsm-agent:latest +``` + +三项必填环境变量(在面板「服务器」页添加服务器后获取): + +| 变量 | 说明 | +| --- | --- | +| `SERVER_ID` | 服务器 ID | +| `SECRET` | 服务器密钥 | +| `WORKER_URL` | 面板上报地址,例如 `https://probedeck.example.com/update` | + +## 可选环境变量 + +| 变量 | 默认值 | 说明 | +| --- | --- | --- | +| `REPORT_INTERVAL` | `60` | HTTP 模式上报间隔(秒);WSS 实时模式不受影响 | +| `COLLECT_INTERVAL` | `0` | 采样间隔(秒),`0` = 跟随上报间隔 | +| `CONNECTION_MODE` | `auto` | `auto` 优先 WSS 实时上报,`http` 仅定时 POST | +| `PING_MODE` | `tcp` | `tcp` 或 `icmp` | +| `RESET_DAY` | `1` | 每月流量重置日 1-31,`0` = 不重置 | +| `INTERFACE` | 空 | 指定统计网卡,多个用英文逗号分隔;空 = 自动汇总 | +| `DEBUG` | `0` | `1` 输出调试日志 | + +## 数据持久化 + +`/etc/cf-probe` 存放 `config.conf` 与 `traffic.dat`(流量计数器),**必须挂 volume**,否则重建容器会丢流量统计、且面板下发的节点/间隔配置也会丢。 + +## 升级 + +```bash +docker pull ghcr.io/gg949/cfsm-agent:latest +docker stop cf-probe && docker rm cf-probe +# 用原 docker run 命令重建(环境变量不变) +``` + +容器内**已禁用自动更新**——容器的升级方式就是重新拉镜像,进程自己替换二进制没有意义。 + +## 查看日志 + +```bash +docker logs -f cf-probe +``` + +## 多架构 + +镜像支持 `linux/amd64` 与 `linux/arm64`(Unraid 多为 amd64;ARM 盒子/部分群晖型号可用)。 + +## Unraid 模板要点 + +- Repository:`ghcr.io/gg949/cfsm-agent:latest` +- 必填环境变量:`SERVER_ID` / `SECRET` / `WORKER_URL` +- 挂载:Host Path `/mnt/user/appdata/cf-probe` → Container Path `/etc/cf-probe`(RW) + +## docker compose + +仓库根有 `docker-compose.yml` 示例,改掉三个占位值后 `docker compose up -d` 即可。