为什么要在飞牛OS上跑一个运动记录服务
我用飞牛OS有一段时间了,它本质上是基于Debian的NAS系统,自带Docker和Docker Compose,管理界面做得比群晖顺手一些。日常我拿它存文件、跑一些轻量容器。之前运动数据一直散在手机App里,各家App导出格式不统一,想做个长期统计很麻烦,所以打算自建一套运动记录服务,数据放自己硬盘上。
选ExerciseDiary的原因很简单:它是一个自托管、带Web界面的运动/健身日志项目,支持记录训练、体重、目标之类的数据,前后端打包在一个镜像里,部署成本低。它并不是那种功能特别庞大的健身平台,但对我这种只想记录+看趋势的需求刚好够用。需要说明的是,ExerciseDiary并不是一个特别主流、更新极频繁的项目,社区规模有限,这一点在选型时要有心理预期。
本文会覆盖三块:Compose部署、运动记录的日常使用、以及外网访问(飞牛自带方案和Cloudflare Tunnel两条路)。远程访问部分我会重点讲思路,因为不同网络环境差异很大,具体到端口和配置要按你自己的情况调整。
部署前的准备

在飞牛OS上,Docker相关操作我基本走两条路:一是Web界面里的Docker应用,二是SSH进去用命令行。Compose文件我倾向用命令行管理,因为改起来直观,日志也好查。
先确认环境:
bash
docker --version
docker compose version
飞牛OS一般已经装好这两样。如果docker compose(带空格,V2语法)不可用,试试docker-compose(带横杠,V1)。现在新系统基本是V2,我下面统一用docker compose。
接着规划目录。我习惯把所有自托管服务的数据集中放,方便备份:
bash
mkdir -p /vol1/1000/docker/exercisediary/data
cd /vol1/1000/docker/exercisediary
/vol1/1000/是我飞牛上的存储池路径,你的可能不一样,用df -h或文件管理器确认一下。ExerciseDiary的数据主要是一个数据库文件(通常是SQLite),所以持久化目录指到data就行。
【注意】ExerciseDiary的官方镜像名称和标签,不同来源说法不完全一致。我在部署时用的是社区常见的镜像名,如果你在Docker Hub搜不到,建议先去项目仓库确认当前推荐的镜像地址。这一点我没有逐一验证所有镜像tag,请以项目README为准。
编写docker-compose.yml

我最终的Compose文件大致长这样:
yaml
services:
exercisediary:
image: exercisediary/exercisediary:latest
container_name: exercisediary
restart: unless-stopped
ports:
- "8383:80"
volumes:
- ./data:/app/data
environment:
- TZ=Asia/Shanghai
几个地方解释一下为什么这么写:
restart: unless-stopped------NAS重启后容器自动拉起,但手动停了不会自己回来,这个策略对家用服务最省心。
ports映射------左边是宿主机端口,右边是容器内端口。这里我假设容器内部监听80。如果项目实际用的是别的端口(比如3000、5000),右边要改。我写作时没法保证所有版本都用80,所以这一步务必以镜像文档为准,或者启动后看日志里打印的监听端口。
volumes------把宿主机./data挂到容器内数据目录。ExerciseDiary的数据路径在不同版本里可能是/app/data,也可能是别的。如果挂载后数据没持久化,八成是路径对不上,进容器看一眼:
bash
docker compose exec exercisediary ls /app
TZ环境变量------让容器用东八区时间,否则记录时间戳会差8小时,做趋势统计时很别扭。
启动:
bash
docker compose up -d
docker compose logs -f
日志里如果出现数据库初始化、监听端口之类的信息,基本就起来了。浏览器访问http://飞牛IP:8383。
【踩坑提醒】如果页面能打开但样式全乱、接口报错,常见原因是反向代理或端口没配对;如果完全打不开,先docker compose ps看容器状态是不是Up,再看日志有没有崩溃堆栈。
运动记录的日常使用
ExerciseDiary的界面逻辑不复杂:新建一条记录,选运动类型,填时长或距离,保存。它一般会提供一个仪表盘,把历史记录按时间轴或图表展示。
我自己的用法是每天训练完随手记一笔,字段不用填太细,重点是坚持。真正有价值的是积累一段时间后看趋势------比如每周总时长有没有下降,某类运动频率够不够。这也是我放弃手机App改用自托管的原因:数据在我手里,导出和二次分析不受限。
数据存在SQLite里的话,备份就是复制文件:
bash
cp /vol1/1000/docker/exercisediary/data/*.db /vol1/1000/backup/exercisediary-$(date +%F).db
【注意】数据库文件在容器运行时直接复制可能拿到不一致的快照。稳妥做法是先停容器再复制,或者用SQLite的.backup命令。我平时是停容器备份,几十秒的事。
远程访问:两条路

本地能用之后,真正麻烦的是外网访问。这里我讲两种方案,各有取舍。
方案一:飞牛OS自带的远程访问
飞牛系统提供了一些远程访问能力(类似内网穿透/中转),可以在不暴露公网端口的前提下从外部访问NAS上的服务。具体入口和配置项在飞牛的设置里,我这边是通过它的远程访问功能把内网服务映射出去。
优点是不用自己搞域名和证书,配置门槛低;缺点是依赖厂商中转,速度和稳定性受中间链路影响,且功能形态可能随系统版本变化。我没有对它的带宽和并发做严格测试,只能说日常打开记录页面够用。
方案二:Cloudflare Tunnel(CR)
如果你有自己的域名、且域名托管在Cloudflare,用Cloudflare Tunnel是个更可控的方案。它的原理是在NAS上跑一个cloudflared容器,主动向Cloudflare建立出站隧道,外部请求经Cloudflare转发进来,全程不需要在路由器上开公网端口。
先在Cloudflare Zero Trust后台创建一条Tunnel,拿到token,然后加一个Compose服务:
yaml
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token <你的TUNNEL_TOKEN>
network_mode: host
把<你的TUNNEL_TOKEN>换成后台给你的实际token。network_mode: host是为了让cloudflared能直接用宿主机的网络访问到ExerciseDiary容器所在的端口,省去跨网络配置的麻烦。
然后在Zero Trust里给这条Tunnel配一个Public Hostname,比如diary.你的域名.com,Service指向http://localhost:8383(即ExerciseDiary在宿主机上的地址)。保存后等几十秒,外网就能访问了。
【关键结论】Cloudflare Tunnel的核心优势是零公网端口暴露 + 自动HTTPS,安全性比直接端口转发高很多。代价是你得有个托管在Cloudflare的域名,并且接受流量经过Cloudflare。
两种方案的对比:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 飞牛自带远程访问 | 配置简单、无需域名 | 依赖中转、速度受链路影响 | 偶尔外网查看、不想折腾 |
| Cloudflare Tunnel | 不暴露端口、自动HTTPS、可控 | 需自有域名、流量经CF | 长期使用、重视安全 |
一个容易忽略的点:认证

不管是哪种远程方案,ExerciseDiary本身如果只有简单登录甚至没有强认证,把界面直接暴露到公网是有风险的。我的做法是在前面加一层认证------Cloudflare Tunnel可以配合Access策略,要求邮箱验证才能访问;飞牛自带方案则看它有没有提供访问控制。
【踩坑提醒】不要把没有认证的自托管服务直接挂公网。哪怕只是运动数据,被人乱改或扫到也是麻烦。
小结
整套跑下来,飞牛OS上部署ExerciseDiary本身不难,Compose文件十几行就够。真正需要花心思的是两处:一是数据持久化路径要和镜像实际结构对上,二远程访问的安全与稳定性。前者靠进容器确认目录,后者根据自己有没有域名、对安全的要求来选方案。
如果你也在飞牛上跑自托管服务,欢迎交流你们的远程访问是怎么做的------尤其是不同宽带环境下Cloudflare Tunnel的实际速度表现,这块我样本有限,还值得多验证。
=备用标题=
- 飞牛OS自建运动记录:ExerciseDiary的Docker部署与外网访问实践
- 用Docker Compose在飞牛OS跑ExerciseDiary并打通远程访问
- 飞牛OS部署ExerciseDiary:从Compose到Cloudflare Tunnel远程访问
- 自托管运动日志ExerciseDiary在飞牛OS上的部署与远程访问配置
- 飞牛OS+Docker:搭建ExerciseDiary运动记录服务并实现外网访问