这是「Docker 好项目」系列的第 8 期。每期挑一个真正能在自己服务器上跑起来、并且能解决具体问题的项目,给出能直接复制的配置。

你现在听歌用谁?QQ音乐、网易云、Apple Music。曲库里你觉得会永久存在的那几首歌,说下架就下架;会员到期,高音质立刻锁回 128k;更别提歌单里那些冷门歌,哪天歌手解约,链接直接变灰。

其实你硬盘里可能已经躺着几百个 G 的 FLAC——买专辑下的、演唱会扒的、老歌挖的,就是没个顺手的入口听。

Navidrome 干的就是这件事:把自己手里的音频文件变成一个私人流媒体服务。Go 写的单二进制,内置 Web 播放器,兼容 Subsonic API——意味着 iOS/Android 上几十个成熟的第三方客户端都能直接连它。GPLv3 开源,23k+ stars,写这篇时最新版 v0.64.0(2026-09-12 发布),修复了一整批安全问题。

Navidrome 效果图

它到底能干什么

  • 流式播放自己的音乐库:网页端就是全功能播放器,专辑墙、歌手页、随机推荐、搜索、播放队列都有,不用装任何客户端
  • Subsonic API 兼容:这是它最值钱的特性。Android 上的 Symfonium、Ultrasonic,iOS 上的 play:Sub、Amperfy,桌面端的 Feishin、Sonixd,全都拿服务器地址 + 用户名密码直接连
  • 多用户:给家里人各开一个账号,各自的播放记录、收藏、歌单互相独立;还能按库分配权限(你的歌单不想让孩子看到就单独建个库)
  • 多库管理(0.62+):音乐一个库、有声书/播客一个库,挂载几个目录就是几个库
  • 歌词与分级评分:支持内嵌歌词和 .lrc/.ttml 等外挂歌词,0.63 起连逐字卡拉 OK 时间轴都能读
  • 分享链接:可以把单曲/专辑生成外链发给朋友(0.64 修掉了一个越权漏洞,建议直接上最新版)
  • 实时转码:内置 ffmpeg,手机在外用流量时按码率转码,不吃流量套餐

它不做的是:不做音乐管理器(刮削改名整理文件交给 beets、MusicTag 这类工具)、不提供任何在线音源、不能像 Jellyfin 那样管电影和图片。它就是一个纯粹的音频流媒体服务。

Navidrome 网页端界面

部署前准备

  • 内存:空载 50MB 上下,1 核 512MB 的小鸡都带得动,是这系列目前最轻的一个
  • 音乐文件:得自己有音频文件。按 歌手/专辑/曲目 的目录结构放最省心,标签(ID3)写得越全,界面识别越准
  • 转码依赖:官方镜像里已经带好了 ffmpeg,不用额外装
  • 端口:默认 4533
  • 数据库:默认 SQLite,存在 /data 里,无需外接数据库

docker run 一行版

先跑起来感受一下:

docker run -d \
  --name navidrome \
  --restart unless-stopped \
  --user 1000:1000 \
  -p 4533:4533 \
  -v /opt/navidrome/data:/data \
  -v /opt/music:/music:ro \
  deluan/navidrome:0.64.0

--user 1000:1000 先用 id -u、id -g 查一下你自己的 UID/GID,换成本机的值。为什么必须写,看下面「配置项」表格。

浏览器打开 http://服务器IP:4533,注册第一个账号即管理员。

国内拉 Docker Hub 超时的话,换 ghcr 的同一份镜像(官方双仓库发布,内容一致):

docker run -d \
  --name navidrome \
  --restart unless-stopped \
  --user 1000:1000 \
  -p 4533:4533 \
  -v /opt/navidrome/data:/data \
  -v /opt/music:/music:ro \
  ghcr.io/navidrome/navidrome:0.64.0

docker-compose 推荐版

正式用建议这样部署。新建目录和文件:

mkdir -p /opt/navidrome/data && cd /opt/navidrome

新建 docker-compose.yml:

services:
  navidrome:
    image: deluan/navidrome:0.64.0
    container_name: navidrome
    restart: unless-stopped
    user: "1000:1000"
    ports:
      - "4533:4533"
    volumes:
      - ./data:/data
      - /opt/music:/music:ro
    environment:
      ND_LOGLEVEL: info
      ND_SESSIONTIMEOUT: 168h
      ND_DEFAULTLANGUAGE: zh-Hans
      ND_ENABLETRANSCODINGCONFIG: "true"
      ND_ENABLEINSIGHTSCOLLECTOR: "false"
      ND_SCANNER_SCHEDULE: "1h"
      # ND_BASEURL: ""
      # ND_BACKUP_PATH: /data/backup
      # ND_BACKUP_SCHEDULE: "0 0 4 * * *"
      # ND_BACKUP_COUNT: 7

启动:

docker compose up -d
docker compose logs -f navidrome

日志里看到监听 4533 就成了。第一次启动会自动全库扫描(ND_SCANNER_SCANONSTARTUP 默认开启),大库要等一会儿。

每个配置项为什么这么写

配置 说明
deluan/navidrome:0.64.0 只能写完整版本号。官方镜像的 tag 规则只有 0.64.0 这种全量版、PR 号和 develop,latest 和 :0.64 这种主次版本 tag 要么没有要么偏开发向——我已经在 registry 里逐个验证过,0.64 是 404。钉全量版本号是唯一稳妥写法
user: "1000:1000" Navidrome 需要 /data 可写、/music 可读,且都归这个 UID:GID 管。注意 PUID/PGID 环境变量对它无效——那是 linuxserver.io 系镜像的约定,官方镜像根本不认,写了也是白写(这是新手第一大坑)。官方文档明确建议用 user: 指令而不是去掉它让容器以 root 跑
./data:/data SQLite 数据库、转码缓存、封面缓存全在这里,这是唯一要备份的目录。放 compose 同目录,搬家整目录拷走
/opt/music:/music:ro 音乐库只读挂载。Navidrome 从不改音乐文件,:ro 是一道保险:容器被攻破也写不了你的曲库。镜像里默认 ND_MUSICFOLDER=/music,所以路径必须挂到 /music
"4533:4533" 对家族多人、手机局域网直连友好的写法。如果你的实例只打算自己通过 HTTPS 反代访问,可改成 "127.0.0.1:4533:4533" 收紧(参考第 7 期 Memos 的做法)
ND_SESSIONTIMEOUT: 168h 登录态有效期,默认 48h——手机客户端两天要重新登一次很烦。个人自用放宽到一周,多人共用或公网暴露的实例保持默认
ND_DEFAULTLANGUAGE: zh-Hans 界面默认简体中文。必须区分大小写,写 zh-hans 或 zh-HANS 都不生效,对应的是源码 resources/i18n 里的文件名
ND_ENABLETRANSCODINGCONFIG: "true" 默认 false,用户改不了自己的转码码率。打开后每个人能在播放器里自选(如手机流量时切 96k),多用户实例建议开
ND_ENABLEINSIGHTSCOLLECTOR: "false" 匿名使用统计上报,默认开启。自托管图的就是数据不出门,关掉
ND_SCANNER_SCHEDULE: "1h" 定时全库扫描周期,默认是 0(禁用)——因为日常增量靠文件监听(watcher)自动触发。挂 1 小时兜底一次,防止监听漏事件(某些网络挂载上 watcher 不可靠)。这里要敲黑板:老教程里写的 ND_SCANSCHEDULE 是改名前的旧变量,现在是「未识别配置项」,0.64 起启动时会明确告警,不会静默生效
ND_BASEURL 反代到子路径(如 https://域名/music)时才需要设,见下文。默认注释掉——根路径反代和直连都不要设它,设了会导致资源路径全错
ND_BACKUP_PATH / SCHEDULE / COUNT 0.60+ 内置的数据库自动备份:路径、cron 周期、保留份数。三件套一起配才生效,默认全关。不想用内置的可以走下文的 tar 方案,二选一即可

配置项远不止这些,完整清单在官方 options 文档里,命名规律是「配置文件里的驼峰 + ND_ 前缀」。

1Panel 怎么搞

Navidrome 目前不在 1Panel 应用商店里,所以走容器 → 编排 → 创建编排这条路:把上面的 docker-compose.yml 原样贴进去,数据目录选在 /opt/navidrome,一键启动。后续升级、看日志、改配置都在面板里点。

音乐文件放哪:

  • 华为云主机:直接 /opt/music 建目录传文件,注意云盘容量和流量
  • 飞牛 NAS 这类有现成曲库的:把 NAS 上的音乐目录挂进容器即可(compose 里 -v /vol1/music:/music:ro 换成你的实际路径),不用复制一份

顺手在 1Panel 计划任务里加一条容器每日重启 or 数据库备份(见下文备份节)。

首次访问与最小可用配置

浏览器打开 http://服务器IP:4533,注册第一个账号——第一个注册的用户自动是管理员。

进后台(右上角头像 → Users)做三件事就算最小可用:

  1. 关掉公开注册:把「Allow new users」相关选项关掉,否则知道地址的人都能来开账号
  2. 建家庭成员账号:给要听歌的人各开一个,密码单独设——Subsonic 客户端就是拿这个账号登录的
  3. 确认曲库已被扫描:首页能刷出专辑就 OK;没出来先看日志是不是 /music 权限问题(报 permission denied 就是 user: 和目录属主没对齐)

之后手机装一个 Subsonic 客户端,填 http://服务器IP:4533 + 账号密码即可。出门在外就把域名反代配上(见下节),客户端地址换成 HTTPS 域名。

联动与告警

Navidrome 不是监控系统,没有告警概念,但有几个往外接的口子:

Prometheus 指标(第 1 期 Uptime Kuma 用户看这里):

environment:
  ND_PROMETHEUS_ENABLED: "true"
  ND_PROMETHEUS_PASSWORD: "换成强密码"

开启后 http://127.0.0.1:4533/metrics 带密码可拉取,接 Prometheus/Grafana 看在线人数、扫描时长、转码耗时。密码不设就是裸奔接口,所以两行要一起出现。最轻量的做法是让 Uptime Kuma 加一个 HTTP(s) 监控打 4533,挂了发通知。

听歌记录同步:支持 Last.fm 和 ListenBrainz 的 scrobble,在个人设置里授权即可,你的播放历史会同步过去,也能反哺「相似歌曲」推荐。

Smart Playlists:用规则语法定义智能歌单(如「最近添加 + 星级 ≥ 4」),服务端定期自动刷新,客户端无需任何插件。

反向代理与 HTTPS

Navidrome 的 Web 端没有 WebSocket 依赖,普通 HTTP 反代即可,比前几期都省心。

用第 2 期的 Nginx Proxy Manager:新建 Proxy Host,域名填 music.你的域名,Forward 到 127.0.0.1:4533(或局域网主机 IP),SSL 页签一键签证书。

用 1Panel 更直接:网站 → 反代 → 新建,代理地址 http://127.0.0.1:4533,然后在网站设置里签 Let's Encrypt 证书。

两个注意事项:

  • 根路径反代(https://music.域名 → 整站)什么都不用改,最推荐。子路径反代(https://域名/music)必须设 ND_BASEURL=/music 并重启容器,否则页面白屏、静态资源 404
  • 分享链接域名:开了分享功能的话,把 ND_SHAREURL 设成你的对外 HTTPS 地址,生成的分享链接才是能直接点开的
  • 0.64 修了一个「伪造 X-Forwarded-For 绕过登录限速」的漏洞,并且现在按可信客户端 IP 计数——反代场景下确保反代传递真实来源头,登录爆破的限速才是准的

踩坑清单

  • PUID/PGID 没有任何效果:官方镜像不认这组变量。要么 user: "1000:1000" + 目录属主对齐,要么别怪界面里曲库是空的
  • /data 不可写:容器起不来,日志报 unable to open database file。chown -R 一下数据目录就行;千万别用「去掉 user: 让它以 root 跑」来修——官方文档明确不建议
  • 老教程的 ND_SCANSCHEDULE:0.60 重构成 ND_SCANNER_SCHEDULE(多了个 R),0.64 起会对未识别配置项打告警。发现日志里出现 unknown option 就去对一遍文档
  • 配置时长不能写负数:0.64 起启动时校验时长格式,-1h 这种以前被默默容忍的值现在会直接拒绝启动
  • 0.64 升级会重写所有 ID:内部 ID 统一重编码成 128 位格式,升级前必须备份数据库;客户端本地缓存的离线下载可能要重新同步。这是本期最大的迁移坑,跨大版本前先看 Release Notes 的 Breaking Changes
  • 手机连不上但网页正常:九成是客户端填了 http:// 而服务已切 HTTPS,或反向代理没放行 /rest/ 路径(Subsonic API 走这条)。NPM 默认全放行,自写 nginx 规则的留意
  • 转码 CPU 占用高:FLAC 转 opus 是 CPU 活,1 核小鸡上多人同时播会卡。把 ND_TRANSCODING_MAXCONCURRENT 设成 2 限并发,或者让局域网用户用 raw 模式直出
  • 国内拉镜像:换 ghcr.io/navidrome/navidrome:0.64.0,官方同一套 CI 推双仓库

备份

要备份的只有 /data 里的 navidrome.db(音乐文件本身在你自己的曲库目录,另有备份策略)。最简单的 tar 方案:

cd /opt/navidrome
docker stop navidrome
tar czf navidrome-backup-$(date +%F).tar.gz data/
docker start navidrome

恢复就是解包回去再启动:

cd /opt/navidrome && docker stop navidrome
tar xzf navidrome-backup-2026-09-21.tar.gz
docker start navidrome

更优雅的是用 0.60+ 的内置备份,挂到 compose 里让容器自己干:

environment:
  ND_BACKUP_PATH: /data/backup
  ND_BACKUP_SCHEDULE: "0 0 4 * * *"
  ND_BACKUP_COUNT: 7

每天凌晨 4 点压缩一份数据库到 /data/backup,自动滚动保留 7 份。注意备份存在 /data 里,真要容灾还是得把这个目录加进整盘备份(1Panel 的备份计划里把 /opt/navidrome 加上即可)。

小结

Navidrome 是这系列目前资源占用最低、部署最快的一期:一个容器、一个端口、一个数据目录,五分钟把自己变成流媒体服务商。而且它站在 Subsonic 生态上,客户端随便挑,不绑架你。

适合:手里有音频文件想集中管理的、家里人各自用手机听歌的、被云音乐下架和会员体系恶心到的。 不适合:完全没有本地音乐文件、指望它替代 QQ 音乐在线曲库的;想顺便管电影和照片的(那是 Jellyfin/Immich 的活儿,见第 4 期)。

下期继续聊另一个 Docker 项目。


项目地址:https://github.com/navidrome/navidrome 官方文档:https://www.navidrome.org/docs/