# 在 Docker 中搭建家庭媒体服务器:Transmission、Jellyfin 和 Telegram 机器人
只需一个晚上,你就能组装出一个功能齐全的家庭媒体服务器,并配备便捷的 Telegram 控制。抛弃 Transmission 过时的界面,换用现代的 Flood UI;跳过手动复制文件,利用 Jellyfin 的自动索引;不再需要持续监控,直接在你的消息应用中收到下载完成通知。一切都运行在网络附加存储 (NAS) 上,只需一条 Docker 命令即可启动。
基于 Docker 的解决方案架构
系统的核心是三个容器,它们通过 CIFS 卷共享通用文件系统。Transmission 负责 torrent 下载,Jellyfin 索引媒体文件并提供观看界面,而 Telegram 机器人则作为控制和通知的用户界面。关键特性是使用带有 CIFS 驱动的 Docker 卷,从而允许在容器内直接挂载网络共享,而无需绑定到主机本地文件系统。
新手常见错误是试图在 Windows 上为网络驱动使用 bind 挂载。由于 WSL2 的特性,此类路径在容器内不可见。解决方案是明确指定卷类型为 cifs,并附带连接参数:
volumes:
downloads:
driver: local
driver_opts:
type: cifs
device: ${SMB_HOST}
o: "username=${SMB_USER},password=${SMB_PASSWORD},vers=3.0,uid=1000,gid=1000,file_mode=0777,dir_mode=0777"
Transmission 和 Jellyfin 这两个服务都使用此卷,但容器内的挂载点不同,从而确保路径一致且无冲突。
设置 Telegram 机器人和自动化
机器人使用 python-telegram-bot 库以 Python 编写,通过 Transmission 的 RPC API 与其交互。它以共享网络栈模式运行于 Transmission 容器(network_mode: "service:transmission"),从而省去额外端口转发并最小化延迟。
机器人主要功能:
- 通过发送 .torrent 文件或磁力链接添加 torrent
- 自动完成通知,附带 Unicode 进度条
- 通过内联消息按钮管理活跃下载
- 通知过滤,避免重启时重复发送
进度条通过简单函数实现:
def progress_bar(pct, width=12):
filled = round(pct * width)
return "█" * filled + "░" * (width - filled)
为避免机器人重启时发送垃圾消息,它会按 ID 跟踪已完成 torrent。启动时,脚本初始化 completed_ids 集合,仅对新完成的下载发送通知。
微调 Transmission 并绕过图片限制
官方 linuxserver/transmission 镜像有个怪癖:每次启动都会覆盖 settings.json 的部分内容,忽略环境变量。这会影响 watch-dir、download-dir 和 incomplete-dir 等设置。解决方案是使用 custom-cont-init.d 机制,它会在初始化后但守护进程启动前运行自定义脚本。
示例脚本 01-fix-settings.sh:
#!/bin/sh
mkdir -p /downloads/Downloads
mkdir -p /downloads/.incomplete
mkdir -p /downloads/watch
SETTINGS=/config/settings.json
if [ -f "$SETTINGS" ]; then
sed -i 's|"watch-dir": ".*"|"watch-dir": "/downloads/watch"|' $SETTINGS
sed -i 's|"watch-dir-enabled": false|"watch-dir-enabled": true|' $SETTINGS
sed -i 's|"download-dir": ".*"|"download-dir": "/downloads/Downloads"|' $SETTINGS
sed -i 's|"incomplete-dir": ".*"|"incomplete-dir": "/downloads/.incomplete"|' $SETTINGS
sed -i 's|"incomplete-dir-enabled": false|"incomplete-dir-enabled": true|' $SETTINGS
fi
另一个问题是安装 Flood UI。新版镜像移除了第三方界面。你需要手动从 GitHub 下载存档并解压到 config/flood-ui/。仓库中包含 setup-flood.sh 脚本用于自动化。
Jellyfin 首次启动与电视集成
启动容器后,打开 Jellyfin 网页界面 http://localhost:8096。初始设置包括创建用户并添加媒体库。将源指向 /media/Downloads——这就是 Jellyfin 容器中共享文件夹的挂载方式。
Jellyfin 会自动:
- 扫描文件夹内容
- 识别内容类型(电影、电视剧)
- 从 TMDB 获取元数据和海报
- 按流派、年份、演员构建直观导航
用于电视观看,安装官方 Jellyfin 应用(支持 Android TV、Apple TV、Fire TV、Roku)。首次启动时,输入主机的本地 IP 和端口 8096。用之前创建的用户登录。
常见问题与功能扩展
没有 NAS?将 CIFS 卷替换为本地文件夹,使用 bind 选项:
volumes:
downloads:
driver: local
driver_opts:
type: none
device: /absolute/path/to/folder
o: bind
想要 VPN?使用 gluetun 容器,并将 Transmission 移至其网络命名空间:
transmission:
network_mode: "service:gluetun"
depends_on:
- gluetun
如何更新?运行:
docker compose pull && docker compose up -d
远程访问?使用 Tailscale 或 Cloudflare Tunnel——比路由器端口转发更安全。
关键要点
- 对于 Windows 上的 Docker Desktop 中的网络驱动,CIFS 卷优于 bind 挂载至关重要
- custom-cont-init.d 机制绕过了官方 Transmission 镜像限制
- 机器人与 Transmission 间的共享网络栈简化了设置并提升了可靠性
- Jellyfin 自动为媒体补充元数据——无需手动调整
- 所有数据存于外部 NAS,使系统免于操作系统重装影响
— Editorial Team
暂无评论。