Folia 多源音乐 歌词动画 Docker Compose 部署:零编译一键拉起私有音乐站
【免费下载链接】folia-major专注于绚丽的歌词动画效果的本地音乐/navidrome/第三方多平台在线音乐播放器项目地址: https://gitcode.com/GitHub_Trending/fo/folia-major
Folia 是主打全屏歌词动画的在线音乐播放器,吃网易云、酷狗、QQ 音乐与 Navidrome 曲库。跟完本篇,你会在 NAS 上拿到一个浏览器地址和三项能力:多源在线播放、Navidrome 本地曲库、歌词动画。
先看它跑起来什么样
docker compose up之后,浏览器访问http://NAS-IP:18080,就是一台能登录、能搜、能放的在线音乐站。
多源播放:三个平台登录后直接搜歌开听。
歌词动效:播放时歌词铺满整屏做动画。
本地曲库:连上 Navidrome,NAS 音乐变卡片。
确认这就是你要的效果后,进入实操,全程只动 NAS 上的一个目录。
开工前 15 分钟体检
目标是排除一切会让后面命令翻车的因素。
软硬件门槛
- Docker Engine 24+,
docker compose version是 v2; - NAS 有可写目录,18080、13000 端口没被占用;
- 终端能执行
openssl; - 浏览器为桌面版 Chromium 系,功能体验完整。
最小文件集
新建空目录(如docker/folia-docker),从仓库下载两个文件放进去:
| 文件 | 一句话作用 |
|---|---|
| compose.yaml | 定义 6 个容器的完整栈 |
| deploy/docker/.env.example | 环境变量模板,复制后改名为.env再填值 |
就这两个文件,其余全部由镜像承担;日后升级也只替换它们。
生成必填令牌
openssl rand -hex 32🔐 把输出的随机串粘贴进.env的SYNC_TOKEN,它是 Sync Server 校验客户端身份用的。这一项没填时,docker compose config会直接报错拒跑,省得你启动后才发现。
三步把服务拉起来
Step 1|校验配置不报错
docker compose config这一步只做解析:变量齐不齐、语法对不对。漏填SYNC_TOKEN或镜像命名空间,这里就会被拦下。
预期:输出渲染后的完整编排,无报错。
Step 2|拉取全部镜像
docker compose pull一条命令取回网关、backend、三个平台接口和 sync-server 共 5 个镜像,耗时取决于网速。
预期:每个镜像依次显示Pulled。
Step 3|启动并等健康检查全过
docker compose up -d --wait--wait等每个服务的healthcheck通过才返回,不用自己猜启动时机;FOLIA_IMAGE_NAMESPACE决定从哪个镜像空间拉取,缺失时整个栈拒跑。
预期:命令正常返回,无服务卡在starting。
三条都满足,就算部署成功:
docker compose ps里 6 个容器全部healthy;- 浏览器打开
http://NAS-IP:18080看到 Folia 首页; curl http://NAS-IP:13000/health返回正常,Sync Server 就绪。
上线后立刻要做的两件事
第一件事,接入 Navidrome 曲库。Folia 本身不存音乐文件,本地音乐由 Navidrome 托管。进 Folia 设置页的 Navidrome 入口,填三个字段:Web 地址(形如http://NAS-IP:4533)、账号、密码,连接成功后专辑、歌单、文件夹会变成卡片,搜索、播放、歌词匹配直接可用。
第二件事,选填项。GEMINI_API_KEY/OPENAI_API_KEY控制 AI 主题生成与 AI 歌词分词,不填不影响在线搜索、播放和歌词显示。.env里NAVIDROME_URL、NAVIDROME_USERNAME、NAVIDROME_PASSWORD三项齐填后,新打开的浏览器会自动登录该 Navidrome,省得每台设备都手动输一遍。⚠️ 能打开 Folia 页面的人都能读到这组凭据,建议专门建一个账号给 Folia 用。
6 个容器各干什么(30 秒架构)
你正在浏览器里打开的,就是 gateway 吐出来的页面:
| 容器 | 角色 | 对外暴露 |
|---|---|---|
| gateway | 入口与路由 | ✅ 18080 |
| backend | Web API | 否 |
| netease-api | 网易云接口 | 否 |
| kugou-api | 酷狗接口 | 否 |
| qq-api | QQ 音乐接口 | 否 |
| sync-server | 数据同步 | ✅ 13000 |
路由规则一句话:/netease/走 netease-api,/kugou/走 kugou-api,/qq/走 qq-api,/api/走 backend,其余落前端页面兜底。
三个平台接口和 backend 都待在内网段里,只有 gateway 与 sync-server 对外开端口,任何设备都绕不过网关直连平台 API。所有容器设了只读文件系统并禁提权,容器被打穿也写不进文件、提不了权。
接外网之前
HTTP 页面不算浏览器的安全上下文,本地音乐目录导入、PWA 离线安装、音频输出设备选择会被直接关掉。想让这些能力可用,就让 NAS 上现成的反向代理终结 HTTPS:
https://folia.example.com/ -> http://127.0.0.1:18080 https://sync.example.com/ -> http://127.0.0.1:13000- 证书要是浏览器信任的完整链,自签名不算数;
- 反代要转发
X-Forwarded-Host、X-Forwarded-Proto: https、X-Forwarded-For,并把 HTTP 重定向到 HTTPS;Folia 前面挂了代理时把代理自身地址填进FOLIA_TRUSTED_PROXIES,gateway 才能还原真实客户端 IP; .env的FOLIA_HTTP_BIND、FOLIA_SYNC_BIND改为127.0.0.1,流量只从代理进来。
⚠️ origin 切换后,原 HTTP 下的 IndexedDB、登录态、本地曲库索引不会自动迁移,需要重新来过。
日常运维四件套
升级:latest不会自动取新镜像,手动执行——
docker compose pull docker compose up -d回退:.env固定FOLIA_STACK_VERSION=1.2.0(现行版本号见 deploy/docker/VERSION),再跑一遍上面两条。
备份:停服、打包、启服,顺序不能少——
docker compose stop sync-server tar -czf folia-sync-backup.tar.gz ./data/sync docker compose start sync-serverSQLite 写入中途打包会损坏,所以先停再压。
查问题:
docker compose ps docker compose logs --tail=200 gateway backend sync-server curl http://NAS-IP:18080/healthz先 ps 看谁不健康,再 logs 翻日志,最后 curl 看网关应答,顺序别乱。更完整的变量说明见 deploy/docker/README.md。
环境变量速查
镜像与端口:
| 变量 | 默认值 | 改之前要知道什么 |
|---|---|---|
FOLIA_IMAGE_NAMESPACE | papersman | 无(必填),缺了整个栈拒跑 |
FOLIA_STACK_VERSION | latest | latest 不自动更新,回退改它 |
FOLIA_HTTP_PORT/FOLIA_SYNC_PORT | 18080/13000 | 仅本机冲突时才要改 |
FOLIA_HTTP_BIND/FOLIA_SYNC_BIND | 0.0.0.0 | 走代理改127.0.0.1 |
AI 与行为:
| 变量 | 默认值 | 改之前要知道什么 |
|---|---|---|
FOLIA_AI_PROVIDER | google | 改完需重建 gateway 与 backend |
FOLIA_FORWARD_CLIENT_IP | false | 打开后登录地点会显示局域网 |
ENABLE_GENERAL_UNBLOCK | false | 网易云通用解锁,默认关 |
同步服务与数据源:
| 变量 | 默认值 | 改之前要知道什么 |
|---|---|---|
SYNC_TOKEN | 无(必填) | 至少 8 位,缺了拒跑 |
FOLIA_SYNC_DATA_DIR | ./data/sync | 备份打包的就是这个目录 |
NAVIDROME_PRESET_ALLOW | private | 控制谁能读预置凭据 |
收尾
整套私有音乐站的持有成本,是一个目录里的两个文件和 6 个容器。浏览器地址发到群里之后,手机、平板、电视也能用同一个入口直接连上。
【免费下载链接】folia-major专注于绚丽的歌词动画效果的本地音乐/navidrome/第三方多平台在线音乐播放器项目地址: https://gitcode.com/GitHub_Trending/fo/folia-major
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考