补充说明
本教程介绍 fan-random(随机壁纸 API)从源码开发、一键发布到目标服务器部署的完整流程。fan-random 的发布采用 GitHub Actions 全自动流水线:本地只需更新版本号、推送 main 分支并打 v* 开头 tag,Actions 会自动编译 linux amd64/arm64 单文件二进制(@yao-pkg/pkg)、打包壁纸图片包、创建 GitHub Release,并构建推送 multi-arch Docker 镜像(Docker Hub + GHCR)。
项目:fan-random|随机壁纸 API 仓库:https://github.com/meimolihan/fan-random 镜像:mobufan/fan-random|ghcr.io/meimolihan/fan-random 编译发布主机:fnOS(Debian,本机 Node.js 环境齐全) 部署测试主机:Debian Linux(amd64/arm64,可 Docker / systemd / 单文件二进制)
重要规则
- 只有推送
v*标签才触发发布流水线,日常推送main不会触发任何构建。build-and-push.sh要求 TAG 必须以v开头且形如v1.0.1,否则不触发发版。- 编译机器 ≠ 业务运行机器;发布全部由 GitHub Actions 云端完成,本地无需交叉编译。
- 二进制内嵌当前平台 Node 运行时,无法本地跨平台交叉编译;流水线使用
@yao-pkg/pkg在 CI 上交叉编译 amd64/arm64。
一、编译发布机(fnOS)环境准备
1.1 安装依赖
apt update
apt install git curl
Node.js 18+(推荐 20,与 CI 的 node-version: '20' 对齐)、npm。GitHub CLI 用于校验发布结果(发布本身由 CI 完成)。
1.2 安装 gh 命令行工具并授权 GitHub
gh auth login
选择 GitHub.com → SSH → 网页授权登录,务必勾选 repo 权限。
校验授权结果
gh auth status
1.3 拉取源码
git clone git@github.com:meimolihan/fan-random.git
cd fan-random
npm install
项目目录结构
fan-random/
├── api/ # Vercel Serverless 端点(index/pc/mp + _manifest.js)
├── public/
│ ├── pc/ # pc 桌面端壁纸(横屏,418 张)
│ └── mp/ # mp 移动端壁纸(竖屏,418 张)
├── photos/ # 原始图片目录(classify 输入)
├── bin/fan-random.js # 内置 CLI 管理命令
├── docker-server.js # Docker/SEA/Systemd 通用 Node.js HTTP 服务器
├── scripts/
│ ├── build.js # 构建脚本(生成 manifest)
│ ├── build-sea.sh # SEA 单文件编译(npm run build:sea)
│ ├── build-and-push.sh # 一键发版脚本(更新版本号+打tag+推送)
│ ├── install.sh # 一键安装脚本(systemd + CLI)
│ └── uninstall.sh # 卸载脚本
├── .github/workflows/release.yml # GitHub Actions 发布流水线
├── docker-compose.yml
├── Dockerfile
├── sea-config.json # SEA 编译配置
└── package.json
二、本地开发调试
# 直接以 Node 运行(当前目录需含 public/ 壁纸目录)
PORT=8000 node docker-server.js
# 生成 Vercel 构建产物 api/_manifest.js
npm run build
# 语法检查
npm run lint
本地编译单文件二进制(Node.js SEA)
npm run build:sea
编译产物输出到 dist/fan-random(约 125MB,内含 Node.js 运行时和全部服务代码)。图片通过 public/ 目录按需读取,与二进制放在一起:
my-deploy/
├── fan-random
└── public/
├── pc/
└── mp/
PORT=8000 ./fan-random # 启动服务(默认端口 3000)
./fan-random --help # 直接运行也可执行 CLI 管理命令
⚠️ SEA 二进制内嵌当前平台的 Node 运行时,无法跨平台交叉编译(发布流水线使用
@yao-pkg/pkg交叉编译 amd64/arm64)。
三、一键发布(推荐)
前置条件:仓库已推送
main,且已在 GitHub 仓库配置DOCKERHUB_USERNAME/DOCKERHUB_TOKENsecrets(Docker Hub 推送用)。
./scripts/build-and-push.sh v1.0.2 --yes -m "本次新增 xxx"
命令参数
| 参数 | 说明 |
|---|---|
TAG(必填) |
形如 v1.0.1,必须以 v 开头 |
--yes |
免交互模式 |
-m "说明" |
写入发版备注 RELEASE_NOTES.md |
内部流程:
- 校验并解析 TAG(
v1.0.1→ 版本号1.0.1) - 检查远端是否存在同名 Release/Tag → 自动
gh release delete -y --cleanup-tag删除重建并清理 tag - 更新版本号:
package.json的"version": "1.0.1" - 写入发版备注
RELEASE_NOTES.md(Docker 拉取命令 + 二进制安装命令) git commit+git push origin main+git tag v1.0.1+git push origin v1.0.1- 触发 GitHub Actions 自动构建发布(无需本地编译),并轮询展示流水线运行状态
v*tag 触发release.yml后,CI 会删除用户手动创建的重复 Release 再重建(gh release delete --yes && gh release create),因此重复发版也安全。
四、GitHub Actions 自动构建发布
推送 v* tag 后触发单条流水线(release.yml,jobs:build-binaries → publish-release → build-docker → sync-cnb):
4.1 build-binaries:编译二进制 + 打包图片
npm i -g @yao-pkg/pkg
pkg -t node20-linux-x64 docker-server.js -o fan-random_linux_amd64
pkg -t node20-linux-arm64 docker-server.js -o fan-random_linux_arm64
tar -czf fan-random_public.tar.gz public
4.2 publish-release:创建 GitHub Release
Release Assets 包含:
fan-random_linux_amd64fan-random_linux_arm64fan-random_public.tar.gz(供二进制安装时部署默认壁纸)
4.3 build-docker:镜像推送
Buildx 构建并推送 multi-arch(linux/amd64 + linux/arm64)镜像:
mobufan/fan-random:latest与mobufan/fan-random:<版本>(Docker Hub)ghcr.io/meimolihan/fan-random:latest与:v版本/:版本(GHCR)
4.4 sync-cnb(可选)
配置 CNB_ACCESS_TOKEN secrets 后自动同步到 CNB 镜像仓库;未配置则跳过(不阻塞整体流水线)。
校验发布结果
gh release view v1.0.1
docker pull mobufan/fan-random:1.0.1
- Release 状态:Published,不是 Draft 草稿
- Assets 内必须存在两个二进制和一个图片包,不要只看源码 zip/tar.gz
测试下载链接有效性
curl -I https://github.com/meimolihan/fan-random/releases/latest/download/fan-random_linux_amd64
返回 302 Found 正常;返回 404 代表附件缺失。
五、目标服务器部署
目标服务器需要 root 权限,已安装 curl。(国内网络可在脚本 URL 前加加速镜像,或设置
FAN_RANDOM_REPO环境变量。)
5.1 systemd 一键安装(推荐生产环境)
# 默认端口 8588,程序目录 /var/lib/fan-random,自动下载预编译二进制
bash -c "$(curl -sSL https://raw.githubusercontent.com/meimolihan/fan-random/main/scripts/install.sh)" -p 8588 -y
# 自定义安装目录、端口、pc/mp 壁纸目录
bash -c "$(curl -sSL https://raw.githubusercontent.com/meimolihan/fan-random/main/scripts/install.sh)" -d /opt/fan-random -p 9000 -pc /data/wallpapers/pc -mp /data/wallpapers/mp -y
安装完成后输出管理命令:
fan-random status # 查看运行方式、端口、访问地址、图片统计
journalctl -u fan-random -f # 查看实时日志
systemctl restart fan-random # 重启服务
5.2 Docker / Compose 部署
bash <(curl -sL gitee.com/meimolihan/cmdbox/raw/master/sh/dc_inst_fan-random.sh)
5.3 升级
直接重跑安装脚本,自动拉取 latest 版本并覆盖二进制,systemd 自动重启:
bash scripts/install.sh -y
/usr/local/bin/fan-random version
六、新版本发布两种模式
模式 1:递增新版本(正式环境,推荐)
cd /vol1/1000/GitHub/fan-random
./scripts/build-and-push.sh 1.0.2 --yes -m "本次新增 xxx"
目标服务器升级,直接重跑安装脚本:
bash -c "$(curl -sSL https://raw.githubusercontent.com/meimolihan/fan-random/main/scripts/install.sh)" -p 8588 -y
/usr/local/bin/fan-random version
模式 2:删除重建同名 Release(仅限内测,无线上用户)
⚠️ 已有服务器依赖该版本绝对禁止执行,会造成旧版本下载 404。
cd /vol1/1000/GitHub/fan-random
# 删除本地与远端git tag
git tag -d v1.0.1
git push origin --delete v1.0.1
# 删除github release
gh release delete v1.0.1 --yes
# 以同版本号重新发布(build-and-push.sh 会自动重建 Release)
./scripts/build-and-push.sh v1.0.1 --yes -m "重新发布"
七、故障排查表
| 现象 | 排查方案 |
|---|---|
| build-and-push 提示 gh 未安装 | gh auth login 授权(repo 权限),或手动执行版本更新+打tag |
| TAG 校验失败 / Actions 不触发 | TAG 必须以 v 开头且为 v x.y.z 格式(如 v1.0.1),release.yml 只监听 v* |
| Actions 运行失败在 setup-node/pkg | 检查 runner 网络;Node 20 由 workflow 锁定版本 |
| Release 无二进制附件 | 检查 workflow build-binaries 任务是否成功;Assets 应由 CI 上传 |
| 下载二进制返回 404 | 检查 Release 是否 Published,Assets 文件名严格匹配脚本 |
| Docker 镜像未推送 | 确认仓库已配置 DOCKERHUB_USERNAME / DOCKERHUB_TOKEN secrets |
| raw.githubusercontent.com 卡住超时 | 国内网络限制,配置代理,或用 FAN_RANDOM_REPO/加速镜像源 |
| 二进制自检失败(损坏或非 fan-random) | install.sh 会校验文件头与 version 自检并自动尝试下一个源 |
| 部署后服务启动失败 | journalctl -u fan-random -n 100 查看日志;检查端口占用、目录权限 |
八、添加 / 替换壁纸后发布
壁纸存放于 public/pc 与 public/mp,修改后:
- 本地验证:
npm run build生成 manifest;PORT=8000 node docker-server.js测试 - 发布:
./scripts/build-and-push.sh v1.0.2 --yes -m "更新壁纸库" - 服务器升级:重跑安装脚本(二进制安装会自动下载最新
fan-random_public.tar.gz图片包,首次安装自动复制;已存在的图片保留并按需新增)
九、极简速查复制块
发布新版本速记
cd /vol1/1000/GitHub/fan-random
./scripts/build-and-push.sh v1.0.2 --yes -m "更新说明"
# 等价分步:
# vim package.json # "version": "1.0.2"
# echo "更新说明" > RELEASE_NOTES.md
# git add . && git commit -m "chore: bump version to 1.0.2"
# git push origin main
# git tag v1.0.2 && git push origin v1.0.2 # 触发 Actions
# 服务器升级
bash -c "$(curl -sSL https://raw.githubusercontent.com/meimolihan/fan-random/main/scripts/install.sh)" -p 8588 -y
本地 SEA 编译速记
cd /vol1/1000/GitHub/fan-random
npm run build:sea # -> dist/fan-random(内含 Node 运行时,直接运行)