Jellyfin 媒体库为空:NAS Docker Compose 挂载路径排查

一个很具体的 NAS 问题。

我在一台 NAS 上用 Docker Compose 跑 Jellyfin,容器能启动,Web 页面也能打开,但是进后台添加媒体库后一直扫不出内容。目录明明在 NAS 上,电影和电视剧也都在,Jellyfin 里就是空的。

这类问题很容易被误判成"Jellyfin 不识别文件"或"刮削器有问题"。实际排下来,大多数时候不是 Jellyfin 本身,而是这几层出错:

  • 宿主机路径和容器内路径混了。
  • Compose 里的 volume 没挂进去。
  • 容器用户没有读目录权限。
  • NAS 重启后外接盘还没挂载,容器先启动了。
  • 媒体库里填的是宿主机路径,而不是容器内路径。

下面按我的排查顺序写一遍。

环境

这次环境大概是这样:

项目 内容
设备 NAS / 小主机都适用
系统 Linux / NAS Docker 环境
服务 Jellyfin
启动方式 Docker Compose
现象 容器正常启动,媒体库为空

先说结论:Jellyfin 后台添加媒体库时,应该填写容器内路径,而不是 NAS 上看到的真实路径。

例如宿主机路径是:

bash 复制代码
/volume1/media/movies

Compose 里把它挂到容器内:

yaml 复制代码
volumes:
  - /volume1/media/movies:/data/movies:ro

那么 Jellyfin 后台媒体库路径应该填:

bash 复制代码
/data/movies

不是:

bash 复制代码
/volume1/media/movies

这个坑非常常见。

先把 compose 写到最小可用

我会先把 Jellyfin 的 Compose 文件压到最小,不急着加反代、硬解、字幕、刮削和插件。

yaml 复制代码
services:
  jellyfin:
    image: docker.1ms.run/linuxserver/jellyfin:latest
    container_name: jellyfin
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
    volumes:
      - ./config:/config
      - /volume1/media/movies:/data/movies:ro
      - /volume1/media/tv:/data/tv:ro
    ports:
      - "8096:8096"
    restart: unless-stopped

这里用 docker.1ms.run/linuxserver/jellyfin:latest 是为了先排除镜像拉取这层变量。如果你团队内部已经有固定仓库,就替换成自己的镜像地址。本文重点不是换哪个镜像,而是把挂载、权限和扫描路径排清楚。

先启动:

bash 复制代码
docker compose pull
docker compose up -d
docker compose logs -f jellyfin

如果这一步都卡住,就先别看媒体库。先把镜像拉取、容器启动和端口访问排完。

第一层:宿主机目录是否真的存在

先在 NAS 上确认目录存在:

bash 复制代码
ls -lah /volume1/media
ls -lah /volume1/media/movies

这里不要只看图形界面。NAS 的文件管理器里看到目录,不代表 Docker 进程一定能看到同一路径。

尤其是外接硬盘、SMB 挂载、NFS 挂载、加密目录,经常会出现:

  • Web 管理界面能看到。
  • SSH 进去路径不同。
  • Docker 启动时挂载点还没准备好。

如果宿主机上路径都不存在,Compose 写得再漂亮也没用。

第二层:容器内能不能看到文件

宿主机目录存在后,再进入容器看:

bash 复制代码
docker compose exec jellyfin sh
ls -lah /data
ls -lah /data/movies

如果 /data/movies 为空,先不要怪 Jellyfin。

通常是 Compose volume 写错了,比如:

yaml 复制代码
volumes:
  - /volume1/movie:/data/movies:ro

但真实目录叫:

bash 复制代码
/volume1/media/movies

也可能是中文目录、空格目录复制时少了一级。我的习惯是直接用 pwd 复制真实路径:

bash 复制代码
cd /volume1/media/movies
pwd

再贴回 Compose。

第三层:媒体库路径不要填宿主机路径

这是最容易漏的一层。

Jellyfin 后台添加媒体库时,要填容器内路径:

bash 复制代码
/data/movies
/data/tv

不要填:

bash 复制代码
/volume1/media/movies
/volume1/media/tv

因为 Jellyfin 运行在容器里,它只知道 Compose 挂进去后的路径。宿主机路径对它来说不存在。

如果你填错路径,可能不会有特别明显的报错,只是扫描不到内容。

第四层:权限别一上来就 chmod 777

很多教程遇到权限问题会直接:

bash 复制代码
chmod -R 777 /volume1/media

我不建议这么做,尤其是 NAS 上有家庭照片、备份和多用户目录时。

先看容器用什么 UID/GID:

bash 复制代码
id

再看目录权限:

bash 复制代码
stat -c "%u:%g %a %n" /volume1/media/movies
ls -lah /volume1/media/movies | head

如果使用的是 LinuxServer 风格镜像,PUIDPGID 要能读媒体目录。媒体目录至少要有读和进入权限:

bash 复制代码
chmod -R a+rX /volume1/media/movies
chmod -R a+rX /volume1/media/tv

注意这里是 a+rX,不是 777

配置目录可以给容器用户写权限:

bash 复制代码
chown -R 1000:1000 ./config

媒体目录我通常只给读权限,避免容器误删或误改原始文件。

第五层:NAS 重启后的挂载顺序

还有一种很隐蔽的情况:NAS 重启后,Docker 比外接盘或远程挂载先起来。

结果就是:

  • 容器启动成功。
  • /data/movies 路径存在。
  • 但里面是空的。

这时要看挂载点:

bash 复制代码
df -h
findmnt | grep media
mount | grep volume1

如果媒体盘还没挂上,先停止 Jellyfin:

bash 复制代码
docker compose down

等存储挂载完成后再启动:

bash 复制代码
docker compose up -d

如果经常发生,可以考虑把媒体盘挂载写进系统启动依赖,或者在 NAS 的任务计划里延迟启动容器。

第六层:硬解和媒体库为空不是一回事

很多人会把"媒体库为空"和"播放卡顿"混在一起。

媒体库为空,优先查:

  • volume 路径。
  • 容器内路径。
  • 目录权限。
  • 挂载顺序。

播放卡顿或转码失败,再查硬解:

bash 复制代码
ls -lah /dev/dri

如果有核显设备,再考虑 Compose 里加:

yaml 复制代码
devices:
  - /dev/dri:/dev/dri

但这不是第一步。媒体库都扫不出来时,先别急着改硬解。

常见现象对照表

现象 优先排查
Jellyfin 页面能打开,但媒体库为空 后台媒体库路径是否填成容器内路径
容器内 /data/movies 为空 Compose volume 宿主机路径是否写错
容器内能看到文件,但扫描不到 权限、文件名、媒体库类型
NAS 重启后突然空库 外接盘或网络挂载是否晚于容器启动
能扫出来但播放卡 转码、硬解、网络带宽
docker compose pull 很慢 先做镜像源预检,避免把拉取问题误判成服务问题

我的最终检查顺序

以后再遇到 Jellyfin 空库,我会按这个顺序排:

bash 复制代码
# 1. 宿主机目录
ls -lah /volume1/media/movies

# 2. Compose 是否生效
docker compose config

# 3. 容器内是否看得到
docker compose exec jellyfin ls -lah /data/movies

# 4. 权限
stat -c "%u:%g %a %n" /volume1/media/movies

# 5. 挂载点
df -h
findmnt | grep media

# 6. 日志
docker compose logs --tail=200 jellyfin

这套顺序比直接重装 Jellyfin 省时间。

小结

Jellyfin 媒体库为空,最常见的原因不是软件坏了,而是 Docker 的路径映射和权限边界没理清。

NAS 上跑容器服务,我现在会先把问题拆成三层:

  1. 镜像能不能稳定拉下来。
  2. 宿主机目录有没有正确挂进容器。
  3. 容器用户有没有权限读取。

第一层可以用毫秒镜像这类镜像入口先做预检;第二层和第三层必须回到 Compose、目录和权限本身。这样排下来,问题会清楚很多。

相关推荐
星栈1 小时前
一个 pg_try_advisory_lock,搞定 CQRS 投影选主
后端·开源
神奇小汤圆1 小时前
面试总被问 Java内存模型和 volatile,为什么总答不到点子上?
后端
Solis1 小时前
吊打 HashTable!ConcurrentHashMap 凭什么成为并发神器
后端
神奇小汤圆1 小时前
同事说Spring循环依赖很简单,直到我们线上炸了...
后端
XovH1 小时前
环境搭建与第一个“Hello, World”:Django 项目结构与 MTV 模式详解
后端
阿丰资源1 小时前
基于SpringBoot的电影评论网站(含源码)
java·spring boot·后端
小码哥0681 小时前
2026版基于springboot的家政服务预约系统
java·spring boot·后端
浪荡Ddddd1 小时前
初识SpringAI:chat篇
后端·程序员
小谢小哥1 小时前
59-消息推送系统详解
java·后端·架构