补充说明
本教程介绍 fan-md 从源码编译、一键发布到目标服务器部署的完整流程。fan-md 的发布采用 GitHub Actions 全自动流水线:本地只需更新版本号、推送 main 分支并打 v* 开头 tag,Actions 会自动编译前端并嵌入 Go 二进制、创建 GitHub Release(fan-md_linux_amd64 / fan-md_linux_arm64)并推送 multi-arch Docker 镜像。
项目:fan-md|云文档(Markdown + OpenAPI 文档服务器) 仓库:https://github.com/meimolihan/fan-md 镜像:mobufan/fan-md 编译发布主机:fnOS(Debian,本机 Go 1.26+ / Node 24+ 环境齐全) 部署测试主机:Debian Linux(amd64/arm64,Docker + Docker Compose)
重要规则
- GitHub 不允许直接覆盖已发布 Release,正式环境版本号单向递增;
build-and-push.sh会自动检测已存在的同名 Release 并删除重建(仅限内测/无人依赖场景)。- 只有推送
v*标签才触发发布流水线,日常推送main不会触发任何构建。- 编译机器 ≠ 业务运行机器;发布全部由 GitHub Actions 云端完成,本地无需交叉编译。
- 发布内容不依赖本地产物:
build-and-push.sh只做版本号更新 + 推送,构建发布全在 CI。
一、编译发布机(fnOS)环境准备
1.1 安装依赖
apt update
apt install git curl
Go 1.26+(确认 go version 正常)、Node.js 24+、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-md.git
cd fan-md
cd fan-md && go mod download
项目目录结构
fan-md/
├── scripts/build-and-push.sh # 一键发布脚本(更新版本号+打tag+推送)
├── scripts/fan-md_backup.sh # 备份脚本
├── scripts/fan-md_recover.sh # 还原脚本
├── .github/workflows/release.yml # GitHub Actions 发布流水线
├── fan-md/ # Go 后端(Iris)
│ ├── main.go
│ ├── version/version.go # 版本号定义(发布时自动更新)
│ └── go.mod # module fan-md, go 1.26
├── web/ # 前端(Vue 3 + TypeScript + Vite + Element Plus)
├── Dockerfile # 多阶段 Docker 构建
├── docker-compose.yml # Docker Compose 配置
├── build.sh / build.bat # 本地构建脚本
└── data/ # 运行时数据目录(md.db + resource/)
二、本地编译(开发调试)
仅本地测试时使用,发布不依赖此步骤:
chmod +x build.sh && ./build.sh
内部流程:npm install + npm run build(web/dist)→ 复制到 fan-md/web → go build,编译后的可执行文件在 ./fan-md 目录下。
Windows 使用 build.bat。
三、一键发布(推荐)
前置条件:仓库已推送
main,且已在 GitHub 仓库配置DOCKERHUB_USERNAME/DOCKERHUB_TOKENsecrets(docker 推送用)。
./scripts/build-and-push.sh v1.0.1 --yes -m "本次新增 xxx"
内部流程:
- 校验并解析 TAG(
v1.0.1→ 版本号1.0.1) - 检查远端是否存在同名 Release/Tag → 自动删除并清理 tag(
gh release delete -y --cleanup-tag) - 更新版本号:
fan-md/version/version.go的Version = "1.0.1"+web/package.json的"version": "1.0.1" - 写入发版备注
RELEASE_NOTES.md git commit+git push origin main+git tag v1.0.1+git push origin v1.0.1- 触发 GitHub Actions 自动构建发布(无需本地编译)
命令参数
| 参数 | 说明 |
|---|---|
TAG(必填) |
形如 v1.0.1,--yes 免交互 |
--yes |
免交互模式 |
-m "说明" |
写入发版备注 RELEASE_NOTES.md |
四、GitHub Actions 自动构建发布
推送 v* tag 后触发单条流水线(release.yml:jobs release → docker):
4.1 Release 任务
- Node 24 构建前端:
npm ci && CI=true npm run build:docker - 前端产物嵌入 Go 源码:
cp -r web/dist fan-md/web - 从
version.go读取版本号 - 交叉编译两个 Release 二进制(
CGO_ENABLED=0):
go build -buildvcs=false -trimpath \
-ldflags="-s -w -X fan-md/version.CommitSHA=${GITHUB_SHA:0:7}" \
-o ../bin/fan-md_linux_amd64 .
go build -buildvcs=false -trimpath \
-ldflags="-s -w -X fan-md/version.CommitSHA=${GITHUB_SHA:0:7}" \
-o ../bin/fan-md_linux_arm64 .
- 创建 GitHub Release,Assets 包含
fan-md_linux_amd64/fan-md_linux_arm64
4.2 Docker 任务
Buildx 构建并推送 multi-arch(linux/amd64 + linux/arm64)镜像:
mobufan/fan-md:latestmobufan/fan-md:<版本号>(如mobufan/fan-md:1.0.1)
校验发布结果
gh release view v1.0.1
docker pull mobufan/fan-md:1.0.1
- Release 状态:Published,不是 Draft 草稿
- Assets 内必须存在两个编译二进制
五、目标服务器部署
fan-md 基于 Docker 部署(镜像 mobufan/fan-md:latest,端口 9900,数据目录挂载 ./data:/fan-md/data)。
5.1 Compose 一键部署(推荐)
bash <(curl -sL gitee.com/meimolihan/cmdbox/raw/master/sh/dc_inst_fan-md.sh)
交互式输入部署目录(默认 /vol1/1000/compose/fan-md)与映射端口(默认 9900),脚本自动检查 Docker 环境、开放防火墙端口、清理旧容器并生成 docker-compose.yml 启动。
5.2 Docker 手动运行
docker run -d --name fan-md --restart always \
-p 9900:9900 \
-v /etc/localtime:/etc/localtime:ro \
-v /home/docker/fan-md:/fan-md/data \
-e reg=true \
mobufan/fan-md:latest
首次使用:访问 http://<IP>:9900,登录页点击注册创建第一个账号,注册完成后建议将 reg 改为 false 关闭注册。
六、新版本发布模式
模式 1:递增新版本(正式环境,推荐)
cd /vol1/1000/compose/opencode/workspace/fan-md
./scripts/build-and-push.sh 1.1.0 --yes -m "本次新增 xxx"
目标服务器升级:
docker pull mobufan/fan-md:latest
docker restart fan-md
# 或重跑一键部署脚本(会重建容器)
bash <(curl -sL gitee.com/meimolihan/cmdbox/raw/master/sh/dc_inst_fan-md.sh)
模式 2:删除重建同名 Release(仅限内测,无人依赖)
build-and-push.sh已内置该逻辑:检测到同名 Release 时自动gh release delete -y --cleanup-tag,再用同版本号重新发布。
cd /vol1/1000/compose/opencode/workspace/fan-md
./scripts/build-and-push.sh 1.0.0 --yes
七、故障排查表
| 现象 | 排查方案 |
|---|---|
| build-and-push 提示 gh 未安装 | gh auth login 授权(repo 权限),或手动执行版本更新+打tag |
| Actions 运行失败在 setup-node/go | 检查 runner 网络;Node 24 / Go 1.26.x 由 workflow 锁定版本 |
| Release 无二进制附件 | 检查 workflow release 任务是否成功;Assets 应由 CI 上传 |
| Docker 镜像未推送 | 确认仓库已配置 DOCKERHUB_USERNAME / DOCKERHUB_TOKEN secrets |
| raw.githubusercontent.com 卡住超时 | 国内网络限制,配置代理,或将安装脚本镜像到 Gitee 中转 |
| 部署后容器启动失败(exit status=127) | docker logs fan-md 查看日志;检查架构、端口占用、./data 目录权限 |
| 本地 cat 之后 fan-md: command not found | 参考用法:./fan-md -p 9900 -log /fan-md/logs -data /fan-md/data |
八、前端 UI 修改流程
前端为 Vue 3 + TypeScript(web/),构建产物内嵌进 Go 二进制(fan-md/web + go:embed):
- 修改
web/src/前端代码 - 本地验证:
./build.sh后运行./fan-md/fan-md -p 9900 - 发布:
./scripts/build-and-push.sh vX.Y.Z --yes - 目标服务器
docker pull mobufan/fan-md:latest+docker restart fan-md升级生效。
九、极简速查复制块
发布新版本速记
cd /vol1/1000/compose/opencode/workspace/fan-md
./scripts/build-and-push.sh 1.1.0 --yes -m "更新说明"
# 等价分步:
# vim fan-md/version/version.go web/package.json # 版本号
# echo "更新说明" > RELEASE_NOTES.md
# git add . && git commit -m "chore: bump version to 1.1.0"
# git push origin main
# git tag v1.1.0 && git push origin v1.1.0 # 触发 Actions
docker pull mobufan/fan-md:latest # 服务器升级
docker restart fan-md