1. 先把需求理清楚:为什么我要用 Docker 搭 Lidarr
Lidarr 这个工具,第一次听名字可能没什么感觉,但用过之后,你会发现它是那种能让人省下几百个小时的工具。简单说,Lidarr 是一个面向音乐库的自动化管理工具,把音乐当成一整个“收藏体系”来对待:它知道你的音乐库里有哪些艺术家、哪些专辑、缺哪几张、每张专辑的曲目顺序该是什么样、封面该长什么样、文件该怎么命名。它的定位和视频领域常见的剧集管理器是一个思路,只是把对象从剧集换成了专辑和曲目。
我用它解决的问题很具体:本地攒了十几年的音乐文件,来源很杂——早年从 CD 抓的轨、买过的数字专辑、朋友拷过来的无损合集、还有一堆命名乱七八糟的文件夹。这些文件散落在几个硬盘里,命名规则有01 - 歌名.mp3、有Track01.flac、还有中文全角空格混着英文半角括号的。播放器扫进去之后,艺术家重复几十个条目,专辑被拆成散装单曲,封面更是十张里有八张是空的。Lidarr 干的活就是把这堆东西按“艺术家 → 专辑 → 曲目”的层级重新组织起来,按统一规则改名、补全元数据、补齐封面,然后持续追踪你收藏的艺术家后续有没有新专辑。
至于为什么一定要用 Docker,而不是直接装到宿主机上——这个选择背后有几条很实在的理由,后面会详细拆。先给结论:Docker 版 Lidarr 把升级、迁移、回滚这三件最烦的事情变成了改一行配置的事。它适合的人群也很明确:手里有一定规模本地音乐收藏、愿意花两三个小时做一次结构化整理、并且希望这套体系能长期自动运转的人。如果你只是偶尔听几十首歌,那用不着它;但只要你的收藏上了千首、跨了几十个艺术家,这套东西的收益就会非常明显。
1.1 Lidarr 到底在管什么,不管什么
很多人对它有误解,以为装上就能自动变出一个完整音乐库。实际上它的能力边界很清晰:它管组织、命名、元数据一致性、缺漏追踪,不管音频本身的质量修复。也就是说,一个码率很低的文件,Lidarr 不会帮你变好;封面糊了,它也不会给你重绘。它的价值在“索引”和“一致性”上。
它内部维护一张自己的数据库,记录每个艺术家的全部专辑列表、每张专辑应有的曲目数和曲目时长、发行年份、专辑类型(录音室专辑、现场、精选、EP 等)。当你把一个艺术家加入监控列表,它就会拿数据库里的“应有状态”去比对你的“实际状态”,然后把差异列出来。这个机制的好处是,你随时能看到“我到底缺了什么”,而不是靠回忆。
需要特别说明的是,Lidarr 处理的是你自己的音乐收藏,它的定位是本地资料库的管理者。至于库里的文件从哪来,那是使用者自己的事,工具本身只是提供整理能力。我在文中所有操作都基于“整理已有本地文件”这个场景展开。
1.2 容器化带来的三个实际好处
第一个好处是依赖隔离。Lidarr 底层依赖一套运行时环境和媒体处理组件,直接装在宿主机上,很容易和系统自带的包版本打架。我早年在一台老机器上装过非容器版本,结果为了凑齐依赖,把系统里另一个服务的运行环境搞坏了,排查了整整一晚上。容器把这一整套东西封在镜像里,宿主机只需要有容器运行时,其他一概不关心。
第二个好处是升级和回滚的成本极低。Lidarr 的版本迭代比较频繁,新版本偶尔会有数据库结构变更。用容器,升级就是拉新镜像、重建容器;如果新版本有问题,把镜像标签改回上一个版本再重建,几分钟就能退回去。非容器部署想回滚,那就得重新走一遍编译或包管理流程,非常折腾。
第三个好处是目录结构清晰、迁移方便。所有状态都收敛在配置目录里,整个服务“搬走”就是把配置目录打包拷到另一台机器,改一下路径映射重新起来。我实际从一台旧机器迁到新机器,全程没超过十分钟,播放端的记录和已下载列表全都还在。
1.3 动手之前必须想清楚的三件事
第一,音乐库放在哪个文件系统上。这决定了你后面能不能用硬链接。硬链接能在“下载目录”和“音乐库目录”之间共享同一份数据,不额外占空间,整理速度也快。但硬链接要求两个目录在同一个文件系统(同一个挂载点)下。如果你的下载目录在 SSD、音乐库在机械盘,那就用不了硬链接,只能走复制,整理大库时会明显慢。
第二,容器内的用户身份。这是新手最容易忽略、也最容易出问题的地方。容器默认可能以某个内部用户的身份写文件,写出来的文件在宿主机上属主很奇怪,导致你后续用别的工具处理时权限不足。解决办法就是启动时指定 UID/GID,让容器内进程用和你宿主机账号一样的身份操作文件。
第三,命名规则要先定好再跑。一旦 Lidarr 按某种规则批量重命名了几千个文件,再想改规则重来一次是可以的,但你的播放端、播放列表、外部刮削记录可能全都要重新扫。所以第一次配置时,建议先拿一个小目录(比如十张专辑)当试验田,跑通了再指向主库。
2. 环境准备与目录规划:这一步偷懒,后面全是坑
2.1 宿主机基础检查
开工前先在宿主机上确认几件事。容器运行时是否已安装并正常启动,这个不用多说;然后是磁盘空间,Lidarr 的配置目录本身很小(几十到几百兆),但如果开启封面缓存、日志留存,长期跑下来也会涨到几个 G,给它留 5G 以上比较稳妥。
再就是文件系统类型。如果你打算用硬链接,务必确认下载目录和音乐库目录在同一个挂载点下。检查方法很直接:
df -h /srv/media/downloads /srv/media/music看两行的Filesystem列是否完全一致。如果一个是/dev/sdb1、另一个是/dev/sdc1,那就不在同一文件系统,硬链接会失败。这种情况下要么把两个目录挪到一起,要么就接受复制模式。
还有一点容易被忽略:路径里尽量不要有中文和空格。Lidarr 本身能处理,但你后续写脚本、做备份、配其他服务时,中文路径会带来一堆转义麻烦。我的习惯是统一用/srv/media/music这种纯英文小写路径,中文只出现在标签和目录名里。
2.2 目录结构设计与权限映射
我用的目录结构是这样,可以直接参考:
/srv/docker/lidarr/config # 容器配置、数据库、日志 /srv/media/music # 音乐库最终存放位置 /srv/media/downloads # 临时下载/待整理区这三个目录分别对应容器内的/config、/music、/downloads。注意/srv/media/downloads和/srv/media/music都在/srv/media下,通常就是同一个文件系统,硬链接没问题。
创建目录并设置属主:
sudo mkdir -p /srv/docker/lidarr/config /srv/media/music /srv/media/downloads id 你的用户名 # 记下输出的 uid 和 gid sudo chown -R 1000:1000 /srv/docker/lidarr /srv/mediaid命令输出的uid=1000(你的用户名) gid=1000(你的用户名)这两个数字,就是后面要写进 compose 文件的PUID和PGID。很多人直接抄网上的1000:1000,恰好自己的账号也是 1000,就以为万事大吉;换一台机器账号 ID 不是 1000,就出问题了。所以这一步一定要自己查,别抄。
提示:如果音乐库需要局域网内其他设备(比如播放器、其他电脑)读取,把目录权限设成
775、父目录设成2775(带 setgid),这样新建的文件会自动继承目录的组,省去后期反复改权限的麻烦。
2.3 UMASK 这个参数值得单独说
UMASK=002这一行在很多教程里被省略,但它决定了容器新建文件的默认权限。默认 umask 往往是022,意味着新建文件是644、新建目录是755——同组用户只能读不能写。如果你的音乐库需要多用户或多服务共同维护,这个权限就不够了。
设成002之后,新建文件是664、目录是775,同组用户可读写。这个改动看起来很小,但它避免了一类非常隐蔽的问题:某个服务写进去的文件,另一个服务想改名或移动时权限被拒,然后你在一堆日志里找原因。我踩过这个坑,那次的症状是“整理任务随机失败”,日志里只有一句很笼统的权限错误,找了两个小时才发现是 umask 的问题。
3. docker-compose 编排:一份可以直接抄的配置
3.1 完整的 compose 文件
我不用docker run那一长串命令,原因很简单:参数一多,改起来容易漏、复制给别人容易错,而 compose 文件本身就是一份配置文档,谁拿到都能看懂。下面这份是我目前在用的,删掉了个人化的部分:
services: lidarr: image: lscr.io/linuxserver/lidarr:latest container_name: lidarr environment: - PUID=1000 - PGID=1000 - TZ=Asia/Shanghai - UMASK=002 volumes: - /srv/docker/lidarr/config:/config - /srv/media/music:/music - /srv/media/downloads:/downloads ports: - "8686:8686" restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8686/ping"] interval: 60s timeout: 10s retries: 3 start_period: 90s启动:
cd /srv/docker/lidarr docker compose up -d docker compose logs -f --tail=50看到日志里出现启动完成、监听端口的记录,就可以打开http://宿主机IP:8686了。
3.2 关键参数逐条拆解
镜像标签为什么用latest。说实话这不是最佳实践,最佳实践是钉死具体版本号,比如:2.x.x。但对于个人自建服务,latest的便利性更高——你不需要经常去查版本号。折中方案是:平时用latest,升级前先备份配置目录,出问题就回退。如果你追求稳定,直接把标签换成具体版本,升级时机完全自己掌控。
restart: unless-stopped的意义。它保证容器在宿主机重启后自动拉起,但如果你手动stop了,它就不会自作主张再起来。比always更符合人的预期,比no更省心。
端口映射的形式。"8686:8686"前面那个是宿主机端口,后面是容器内端口。如果你的 8686 被别的服务占了,改成"18686:8686"就行,容器内部不用动。有一种做法是前面只写"8686",让 Docker 随机分配宿主机端口——不推荐,因为你重启容器端口可能变,收藏夹里的地址就失效了。
健康检查为什么加。上面那个/ping接口是判断服务是否真正就绪的轻量方式。加了健康检查之后,docker ps里能看到healthy状态,配合一些自动化脚本可以做到“服务真的起来了再执行下一步”。不加也能用,但排查启动慢的问题时少了一个判断依据。
注意:健康检查里用到的
curl命令,取决于镜像内部是否自带。如果镜像里没有 curl,健康检查会一直显示 unhealthy,但不影响服务本身。遇到这种情况,把健康检查整段删掉即可,不要为了它去折腾镜像。
3.3 网络模式与访问方式的选择
默认的桥接网络加端口映射,对绝大多数场景够用。如果你在同一台机器上还跑着下载器、播放服务等其他容器,想让它们互相通信,可以把它们放进同一个自定义网络:
networks: media-net: driver: bridge然后各个服务都加上networks: [media-net],容器之间可以直接用服务名互相访问,不用走宿主机 IP。这个改动的好处是:以后你换宿主机的内网 IP,容器之间的连接配置完全不用改。
至于要不要用network_mode: host,我的建议是能不用就不用。host 模式确实省掉了 NAT 层,性能上有一点点收益,但它会让端口直接占用宿主机,多个服务抢同一个端口时排查起来很麻烦,而且失去了容器网络隔离的意义。媒体管理这类服务对网络延迟完全不敏感,没必要为这点性能牺牲可维护性。
4. 首次启动后的初始化:把规则定死
4.1 基础设置与界面语言
第一次打开会进一个初始化页面,要求设置访问认证方式和音乐库根目录。认证方式按需选,如果这台机器只在局域网内使用,表单认证就够;如果要暴露到外网(不建议直接暴露,至少加一层反向代理和额外认证),务必设强密码。
界面语言可以在设置里改成中文,但我的建议是先用英文跑一段时间。原因很实际:社区里绝大部分教程、报错信息、参数名都是英文的,中文界面下的选项名称你去搜索,命中率会低很多。等熟悉了再换回中文,体验更好。
4.2 根目录与媒体管理设置
根目录(Root Folder)指向容器内的/music,也就是宿主机的/srv/media/music。这里有个细节值得注意:根目录下不要再嵌套另一个根目录。有些人喜欢搞/music/无损、/music/流行这种分类,然后加多个根目录。这样做不是不行,但会让“艺术家文件夹”的层级变深,某些播放端扫描时容易出问题。我的做法是只保留一个根目录,分类需求通过标签和视图去满足,不靠物理目录。
媒体管理里有几个开关,说下我的取舍:
| 设置项 | 我的选择 | 理由 |
|---|---|---|
| 重命名文件 | 开启 | 统一命名是整套体系的基础,不开等于白搭 |
| 整理时忽略文件 | 关闭 | 保证库内一致性,避免残留脏文件 |
| 创建空艺术家目录 | 关闭 | 空目录没意义,还会干扰扫描 |
| 回收站 | 开启,保留 7 天 | 误删或误改名的后悔药,非常值得 |
| 导入额外文件 | 开启 | 保留封面图片、说明文件等附件 |
| 未映射文件处理方式 | 复制 | 保守策略,宁可多占空间也不丢数据 |
回收站这一项我要多说两句。它不是垃圾桶,而是把被替换或删除的文件移到指定目录,保留一段时间。我配置的时候觉得没必要,直到有一次质量配置写错,让系统把一批无损文件“替换”成了低码率版本,原始文件直接被清掉了。那次损失了大概二十张专辑,只能重新抓轨。之后我把回收站打开,保留期设成 7 天,再也没出过类似问题。
4.3 质量配置文件怎么调
质量配置文件(Quality Profile)决定了系统认为“什么算合格的文件”。这里的逻辑不是“越高越好”,而是“按你的实际需求和存储条件排序”。
我的建议是分两套:
- 主力收藏:只接受无损格式,明确排序,低于阈值的一概不要。
- 杂项合集:接受高码率有损格式,重在覆盖广度,不追求极致。
具体操作是新建一个配置文件,在质量列表里把不需要的格式全部取消勾选,然后把想要的格式拖动排序。排序靠上的优先级更高。这里的关键理解是:列表顺序代表“当同一个专辑有多种格式可选时,优先保留哪个”。如果你把有损格式排在无损上面,系统在替换文件时会用有损版本覆盖无损版本——这就是我前面提到的那个事故的直接原因。
还有一个“升级直到”的概念,指的是“满足什么条件就不再继续找更好的版本”。如果你的库里已经有大量无损文件,把这一项设成无损,能有效减少无谓的搜索和替换动作。
4.4 命名规则:一次定好,长期受益
命名规则是整个体系里最有“复利”的一环。定得好,以后所有新增内容自动整齐;定得随意,几年后你还得再来一次大整理。我用的目录与文件命名规则大致是这样:
{Artist Name}/{Album Title} ({Release Year})/{Medium Format} {track:00} - {Track Title}效果是:
某艺术家/某专辑 (2019)/CD 01 - 曲目名.flac拆开说几个要点。{track:00}里的00表示两位数补零,这样排序时02会正确排在10前面,不会出现1, 10, 2这种字典序错乱。{Medium Format}用来区分 CD、黑胶转录、数字版,同一张专辑有多个版本时不会互相覆盖。{Release Year}放在专辑名后面加括号,是几乎所有播放端都能正确识别的惯例格式。
提示:改命名规则之后,不要立刻对全库执行。先选一个艺术家,手动触发一次重命名,去文件管理器里看看实际效果,确认没问题再放大到全库。我在这一步吃过亏——某次把分隔符写成全角字符,跑完全库才发现几百个文件名都带着奇怪的空隙。
5. 与周边服务的联动:让它真正跑起来
5.1 下载客户端的接入
Lidarr 可以和常见的下载器对接,形成一个“发现 → 获取 → 整理”的闭环。配置位置在设置里的下载客户端板块,填主机、端口、账号密码、以及两个路径:一个是下载器视角下的保存路径,一个是 Lidarr 视角下看到的同一目录。这两个路径必须指向同一个物理位置,否则整理时会报“找不到文件”。
这是新手最高频的踩坑点。举个例子:下载器是另一个容器,它把文件存到自己的/data/completed,映射到宿主机是/srv/media/downloads;而 Lidarr 容器把宿主机同一目录映射成/downloads。那在 Lidarr 的下载客户端配置里,远程路径要填下载器视角的路径,本地路径填/downloads。两边对不上,就会出现“任务完成了但整理不动”的现象。
5.2 元数据与封面的获取策略
元数据这块,Lidarr 依赖外部的音乐数据库来补全专辑信息。国内网络环境下这一步偶尔会慢,表现是添加艺术家之后信息半天不出来。解决办法不是反复重试,而是先确认这台机器能不能正常访问外部服务——很多时候是 DNS 解析的问题,在 compose 里给容器指定一个可靠的 DNS 就能解决。
封面缓存在配置目录里,第一次大批量添加艺术家时会明显涨体积。如果你对封面清晰度要求不高,可以在设置里限制缓存的图片尺寸,能省不少空间。我的做法是保留原始尺寸,因为封面一旦被压缩,后续换更大屏的播放端就没法看了。
5.3 与播放端的配合
Lidarr 自己不是播放器,它只管文件。你需要在播放端(比如各种自托管的音乐流媒体服务)指向同一个音乐库目录,让播放端去扫描。这里有个顺序问题:先让 Lidarr 整理完,再让播放端扫描。反过来做的话,播放端会先索引一堆命名混乱的文件,等 Lidarr 重命名之后,播放端里的记录就全失效了,还得重新扫一遍。
我的习惯是给播放端设一个定时扫描,时间放在凌晨,避开 Lidarr 的整理时段。两者的扫描时间错开,能避免大量文件同时被读写导致的卡顿。
6. 日常运维与问题排查实录
6.1 常见问题速查表
| 现象 | 大概率原因 | 处理方式 |
|---|---|---|
| 页面打不开,容器状态是 running | 端口被占或防火墙拦截 | docker port lidarr看实际映射,再查本机防火墙规则 |
| 添加艺术家后一直转圈无信息 | 容器内 DNS 解析异常 | 给容器指定可靠 DNS,重启后重试 |
| 整理任务报“找不到文件” | 下载器路径与 Lidarr 路径映射不一致 | 核对两边的远程/本地路径是否指向同一物理目录 |
| 文件写出来属主是 root | PUID/PGID 没设或设错 | 用id查真实 ID,修正后重建容器 |
| 硬链接失败,退化成复制 | 两个目录不在同一文件系统 | df -h确认挂载点,或改用复制模式 |
| 无损文件被低码率版本替换 | 质量配置文件排序错误 | 检查质量列表顺序,把无损拖到最上 |
| 重命名后播放端记录全丢 | 先扫描后整理,顺序反了 | 让播放端重新全量扫描一次 |
| 容器频繁重启 | 内存不足或配置目录权限异常 | docker stats看内存,docker logs看退出原因 |
| 中文专辑名变乱码 | 文件名编码或时区/区域设置问题 | 确认TZ配置,尽量用 UTF-8 命名 |
| 数据库损坏导致启动失败 | 非正常关机或磁盘满 | 用配置目录里的自动备份恢复 |
6.2 备份与升级的正确姿势
Lidarr 的配置目录里有一个自动备份机制,会定期打包数据库。但这个自动备份只覆盖数据库,不覆盖封面缓存和自定义配置。所以我做的是两层保险:容器层面依赖自动备份,宿主机层面每周做一次整目录打包。
# 停容器再备份,保证数据库一致 docker compose stop lidarr tar -czf /srv/backup/lidarr-$(date +%F).tar.gz -C /srv/docker lidarr docker compose start lidarr停机这一步别省。SQLite 数据库在运行中直接复制,有可能拷到一个写了一半的状态,恢复时打不开。我吃过这个亏,那次备份文件解压后数据库报损坏,只能从头配置。
升级流程我固定成四步:备份配置目录 → 拉新镜像 → 重建容器 → 观察日志和界面是否正常。如果新版本有问题,把镜像标签改回旧版本重建就行,因为配置目录还在。有一点要提醒:大版本升级可能会改数据库结构,降级时旧版本不一定能读新结构的数据库。所以升级前那份备份是唯一可靠的退路,不要跳。
6.3 我踩过的几个坑和对应的经验
第一个坑是“一次性把整个库丢进去”。我最初直接把存了十几年的音乐目录整个指向根目录,然后触发全库扫描。结果扫描跑了几个小时,中间因为我强行刷新页面导致任务中断,数据库里留下了一堆半成品记录,界面上的艺术家列表一半正常一半是空壳。后来我是清空数据库重来的——把根目录先指到一个只有十张专辑的子目录,跑通整个流程,确认命名、质量、元数据都符合预期,再逐个添加艺术家。
第二个坑是“忽略日志”。Lidarr 的日志分级做得不错,但默认界面只显示一部分。真正的错误细节要去看配置目录下的日志文件,或者docker compose logs。我有一次排查整理失败,界面上只提示一句“导入失败”,翻日志才看到是某个文件的扩展名和实际编码不匹配,被判定为无法识别。这种信息不翻日志永远看不到。
第三个坑是“给容器分配了太多 CPU”。听起来反直觉,但整理任务本质上是大量文件 IO,不是 CPU 密集。我给容器限了很高的 CPU 份额,结果整理时把宿主机上其他服务都拖慢了,而整理速度并没有变快——瓶颈在磁盘随机读写上。后来我把整理任务安排在夜间,并且限制并发数,整体体验好很多。
提示:如果你用的是机械盘,建议把整理任务的并发数调低。机械盘随机 IO 本来就弱,多任务并发反而互相拖累,串行处理的总耗时往往更短。
6.4 一个容易被忽略的细节:时区
TZ=Asia/Shanghai这一行看起来无关紧要,但它影响日志时间戳、定时任务触发时间、以及文件时间属性的解读。我曾经因为没设时区,容器默认走 UTC,结果定时整理任务在本地时间早上八点触发——正好是我用电脑最频繁的时候,机器卡得没法干活。查了半天才发现是时区差了八小时。这种问题不设时区就永远存在,设了就一劳永逸。
另外,时区设置正确之后,日志里的时间和你的直觉一致,排查问题时少一层心算。这看着是小事,但排查紧急问题时,任何一层额外的认知负担都可能让你错过关键线索。
6.5 长期运行的一点体会
这套东西跑了大半年之后,我最大的感受是:前期的规则设计比后期的任何优化都重要。命名规则、质量配置、目录结构这三样一旦定下来,后面新增的内容会自动归位,你几乎不需要干预。反过来,如果这三样是随手配的,跑一段时间之后你会面对一个比整理前更乱的库——因为它是“有规则地乱”,改起来更麻烦。
另外一个实际体会是,不要追求一步到位。我见过不少人一开始就想把所有细节配到完美,结果在配置阶段耗掉大量精力,还没开始用就放弃了。合理的节奏是:先把最小可用的流程跑通(一个艺术家、几张专辑、完整走一遍),确认能用,再逐步加规则、加联动、加自动化。每加一层都验证一次,出问题立刻知道是哪一层引起的。
最后分享一个我一直在用的小习惯:每次改动配置之前,在配置目录里留一个文本笔记,写清楚改了什么、为什么改、改完之后的现象。这个笔记不占空间,但半年后你回头看,能省下大量“当初为什么这么配”的困惑。配置文件本身不会告诉你设计意图,而人的记忆靠不住。