☰
openGym项目架构总览:2个容器+1个文件夹如何撑起一款现代健身App
2026/10/7 7:58:35 网站建设 项目流程

openGym项目架构总览:2个容器+1个文件夹如何撑起一款现代健身App

【免费下载链接】openGymSelf-hosted gym & body-weight tracker — plan routines, log workouts (supersets, warm-ups, cardio), see which muscles are trained, fatigued or detrained, import from FitNotes/Strong/Hevy, passkey login. Your data, your server.项目地址: https://gitcode.com/GitHub_Trending/op/openGym

openGym 是一款自托管健身与体重追踪 App:计划训练、记录组间与力竭、查看肌肉疲劳与恢复,还能从 FitNotes / Strong / Hevy 导入历史数据,用 Passkey(面容/指纹)登录,数据完全存你自己的服务器。它没有复杂微服务——整个服务端就是2 个容器 + 1 个你拥有的数据文件夹,一条docker compose up就能跑起来。下面用 5 分钟带你看完它的架构全景 🏋️

一、架构 30 秒速览:一张图看懂整体结构

官方架构图中,手机或电脑浏览器通过 HTTPS 只访问web 容器(nginx),由它转发/api请求到api 容器(Node.js);API 把所有数据写成 JSON 文件放进./data文件夹。首次启动时,一个一次性的media 服务会下载约 140 MB 的动作示意图(仅首次),之后不再运行。AI 教练与 MCP 服务器都是可选项,默认关闭:

这套结构对应 docker-compose.yml 里的 3 个 service:

服务角色是否常驻
web构建 React 前端 + nginx 托管,代理/api✅ 常驻
api无框架 Node 后端 + Passkey 登录 + 推送通知✅ 常驻
media首次启动下载动作图片/GIF 到共享卷⚡ 一次性

二、web 容器:多阶段构建 + 单端口入口

web/Dockerfile 采用多阶段构建:

  1. build 阶段:node:22-alpine里跑 Vite,把frontend/编译成纯静态文件;
  2. serve 阶段:把静态文件拷进nginx:alpine,启动即用。

自托管者本地完全不需要装 Node。真正的设计亮点在 web/nginx.conf.template:

  • 静态页面与/api代理同处一个 origin(同源),这是WebAuthn Passkey 登录的硬性要求;
  • 配置模板在容器启动时由环境变量渲染(NGINX_PORT、BACKEND、PORT、BASE_PATH),意味着改端口、挂子路径/gym部署都不需要重新构建镜像;
  • /api用变量 +resolver实现每次请求动态解析 api 容器地址,避免容器重建后 IP 变化导致 502;
  • 代理时覆盖(而非追加)X-Forwarded-For头,防止客户端伪造活动日志里的 IP。

三、api 容器:只有 1 个主文件的 Node 后端

后端 api/server.js 是纯node:http,零框架,依赖少到可以数出来:api/package.json 中生产依赖仅 3 个——@simplewebauthn/server(Passkey 登录)、web-push(休息计时器/训练提醒推送)、undici。加一个可选依赖用于 AI 教练。

几个值得新手学习的设计:

  • 状态即 JSON 文件:无数据库。db.json存用户与凭据,state-<用户id>.json存每个用户的计划、训练记录、体重与设置,写入采用"写临时文件再原子改名"防止损坏;
  • 路由即对象键:routes['GET /api/health']这样的键匹配请求方法与路径,加接口只需加一个键;
  • 会话用 HMAC 签名 Cookie,密钥存在./data/secret,不依赖 JWT 或服务端会话存储;
  • 默认与教练双镜像:api/Dockerfile 用两个 build target 从同一份文件出两种镜像——default不含任何 AI 运行时,coach才装 Claude Agent SDK,并创建一个无权读取/data的降权用户,把 AI 运行时与你的数据隔离开。

四、1 个文件夹:./data就是全部数据

整个项目的"数据库"就是主机上的 ./data 目录,映射进容器的/data:

文件内容
db.json用户档案与 Passkey 公钥
state-<用户>.json每个用户的计划、训练、体重、设置
secret会话 Cookie 签名密钥
audit.log登录/管理活动日志(滚动保留)
vapid.json推送通知密钥(自动生成)

备份 = 打包这个文件夹,一行tar完事。Passkey 私钥永远在手机的安全硬件或密码管理器里,不上服务器。

五、多设备同步:版本号 + 乐观合并

手机和笔记本同时登录时,同步靠服务端修订号(revision):设备保存时带上它最后看到的版本;如果期间另一台设备写过,服务器返回409 冲突+ 当前文档,设备本地合并后重试。整个过程见官方时序图:

断网期间的修改不会被丢弃,应用会显示离线横幅提示你何时恢复同步。

六、可选扩展:默认关闭的 AI 教练与 MCP 服务器

  • AI 教练(API_TARGET=coach构建):帮你起草一周训练计划、根据记录建议调整,所有改动需你批准,且使用你自己的API Key,跑在你的服务器上,见 docs/AI_COACH.md;
  • MCP 服务器:只读的标准输入输出桥,让 Claude Desktop、Cursor 等 AI 客户端直接读取你的训练历史与 1RM,不走网络、不占容器,见 mcp/README.md。

七、快速启动步骤

装好 Docker 后:

git clone https://gitcode.com/GitHub_Trending/op/openGym cd openGym cp .env.example .env docker compose up -d

打开http://localhost:8080,创建档案即可。首次启动会一次性下载动作媒体(约 140 MB)。想让手机用 Passkey 登录需要 HTTPS 域名,只需改.env两行——docs/SELF_HOSTING.md 覆盖 Cloudflare Tunnel、Caddy、Traefik、nginx 等全部方案,Kubernetes 部署见 docs/SELF_HOSTING_KUBERNETES.md。

八、关键路径速查

想了解去哪里看
项目结构与架构一页通CLAUDE.md
训练逻辑(渐进规则、1RM、恢复模型)frontend/src/lib/progression.js、frontend/src/lib/onerm.js
API 全部路由(OpenAPI 规范)api/openapi.yaml
常见问题(iPhone、费用、数据去向)docs/FAQ.md
手机端 APK 与 PWA 方案docs/MOBILE.md

结语:极简,却五脏俱全

openGym 的架构哲学可以概括为一句话:把"现代 App 的体验"装进"两个容器 + 一个文件夹"里。单 origin 保 Passkey、JSON 文件保可备份、模板化 nginx 保零构建部署、原子写入保数据安全——每个设计决策都服务于"你的数据,你的服务器"这一承诺。对于想学习小型自托管服务如何从零搭起的同学,这个仓库几乎是最好的范本 📦

【免费下载链接】openGymSelf-hosted gym & body-weight tracker — plan routines, log workouts (supersets, warm-ups, cardio), see which muscles are trained, fatigued or detrained, import from FitNotes/Strong/Hevy, passkey login. Your data, your server.项目地址: https://gitcode.com/GitHub_Trending/op/openGym

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询