前言
qBittorrent 部署在 Alpine LXC 的 Docker 中,下载文件保存到 QNAP,共享通过 NFS 挂载到 LXC。应用配置和任务记录保存在小主机本地。本文记录通过 Portainer 创建容器、设置权限和端口、验证下载、更换 VueTorrent 界面,以及已有任务的导入。
一、环境与目录规划
基础环境见 NAS 折腾日记(2)PVE 与 Docker 基础环境部署,Portainer 操作见 NAS 折腾日记(3)Portainer 部署与容器管理。以下使用 Docker LXC 地址 192.168.20.30,目录均为脱敏示例。
| 内容 | LXC 路径 | 容器内路径 |
|---|---|---|
| 配置与任务记录 | /srv/appdata/qbittorrent/config |
/config |
| NAS 下载目录 | /mnt/nas/downloads |
/downloads |
实际使用的是 LinuxServer 的 qBittorrent 镜像。新部署将整个 /config 绑定到一个本地目录,下载文件单独映射到 NAS。
二、准备目录与权限
在 Docker LXC 中执行:
bash12345mkdir -p /srv/appdata/qbittorrent/config chown -R 1000:1000 /srv/appdata/qbittorrent chmod -R u+rwX,g+rX,o-rwx /srv/appdata/qbittorrent mount | grep ' /mnt/nas/downloads ' ls -ldn /mnt/nas/downloads
挂载输出应为 QNAP 的 NFS 共享。NAS 上的下载目录需要允许 UID/GID 1000:1000 写入;按 QNAP 共享权限和用户映射设置,对已有文件保留其使用者需要的权限。
通过临时容器按应用身份验证读写:
bash1234docker run --rm --user 1000:1000 \ --mount type=bind,src=/mnt/nas/downloads,dst=/downloads \ alpine:3.22 sh -c \ 'probe=$(mktemp /downloads/.qbit-write-test.XXXXXX) && echo ok > "$probe" && cat "$probe" && rm "$probe"'
应输出 ok。若报权限错误,先处理 NAS 共享权限,再启动应用。测试文件使用随机名称,完成后删除。
三、通过 Portainer 创建容器
在 Containers → Add container 填写:
| 字段 | 示例值 |
|---|---|
| Name | qbittorrent |
| Image | lscr.io/linuxserver/qbittorrent:latest |
| Network | bridge |
| Restart policy | Unless stopped |
实际镜像使用 Docker Hub 的 linuxserver/qbittorrent 名称;这里采用 LinuxServer 官方文档给出的仓库入口。表中的 latest 是更新通道,会随发布变化。需要固定版本时,在部署前将它换为选定的版本标签或镜像 digest,并保留同一组运行参数。
3.1 环境变量
在 Env 中逐项增加:
| 变量 | 值 |
|---|---|
PUID |
1000 |
PGID |
1000 |
TZ |
Asia/Shanghai |
WEBUI_PORT |
8080 |
TORRENTING_PORT |
6881 |
这个镜像通过 PUID/PGID 设置应用用户,User 字段保持镜像默认。变量和端口定义见 LinuxServer 镜像文档。
3.2 端口与挂载
添加以下端口发布:
| Host | Container | 协议 | 用途 |
|---|---|---|---|
8080 |
8080 |
TCP | WebUI |
6881 |
6881 |
TCP | Peer 连接 |
6881 |
6881 |
UDP | Peer 连接 |
将环境变量和对应容器端口一起调整。例如 WebUI 改成 8082 时,WEBUI_PORT、容器端口和映射按该端口保持一致。
Volumes 中添加两个 Bind:
| Host | Container |
|---|---|
/srv/appdata/qbittorrent/config |
/config |
/mnt/nas/downloads |
/downloads |
点击 Deploy the container,等待启动后打开 Logs。初次运行在日志中读取临时管理员密码,用户名为 admin。访问 http://192.168.20.30:8080 登录,在 WebUI 设置中修改管理员密码并保存。
四、应用设置与验证
在设置中将默认保存路径设为 /downloads,Peer 监听端口与 TORRENTING_PORT 保持一致。需要未完成目录时,在同一共享内创建子目录,例如 /downloads/incomplete,并配置完成后的保存位置。
先添加一个公开 Linux 发行版种子,确认任务能够开始、下载目录有文件、日志没有写入错误。完成后执行校验,确认任务与磁盘文件对应。
bash1234# 在 Docker LXC 检查 docker logs --tail 80 qbittorrent docker inspect --format '{{range .Mounts}}{{println .Type .Source "->" .Destination}}{{end}}' qbittorrent ls -ln /mnt/nas/downloads
需要外部 Peer 主动连接时,在路由器将选定的 TCP/UDP Peer 端口转发到 Docker LXC 的同名发布端口,并检查对应防火墙规则。WebUI 使用内网访问;域名访问可以按 NAS 折腾日记(7)Lucky 部署与反向代理 配置。
4.1 IPv6 与链路聚合
历史部署时讨论过通过 Portainer 配置 IPv6。LXC 获得 IPv6 地址后,容器能否使用 IPv6还取决于 Docker 网络设置、地址规划、路由和防火墙。本篇使用 bridge 网络完成基础部署,扩展 IPv6 时先查看目标 Docker 网络的 EnableIPv6 和 IPAM 配置,再在容器中确认地址与路由。
J4125 与 QNAP 使用双千兆 XOR 聚合。下载目录的 NFS 访问经过这段网络,应用并发量与链路利用率取决于连接和哈希分流,具体连接关系见基础篇。
4.2 更换为 VueTorrent
种子积累到三五千个后,我这里原版 WebUI 已经出现明显卡顿,打开列表、筛选和操作任务都受影响,因此改用 VueTorrent。原版界面首次同步会取得全量任务状态,浏览器需要维护整个任务列表;后续则通过 rid 增量同步变化,并非每次刷新都重新传输全部数据,相关实现见 qBittorrent WebUI 源码。
VueTorrent 提供分页显示,可以减少同时展示的任务条目,降低大列表的渲染负担。这里主要改善浏览器端的操作体验,全量状态同步和前端排序仍有开销,下载引擎及 NAS 读写性能也不会因为换 UI 自动提高。分页实现见 VueTorrent 的列表页面。
安装并启用
本文使用 LinuxServer 镜像,直接按 VueTorrent 安装文档 加入 Docker Mod:
-
在 Portainer 打开
qbittorrent,点击 Duplicate/Edit。 -
在 Env 添加下列变量;如果已有其他 Mod,在原值后用
|拼接,不要覆盖原配置。变量 值 DOCKER_MODSghcr.io/vuetorrent/vuetorrent-lsio-mod:latest -
保留原来的
/config、/downloads、PUID/PGID 和端口,重新部署同名容器。重建期间下载与做种会短暂中断。 -
查看日志,确认 Mod 下载、安装完成,再检查容器内文件:
bash123# 在 Docker LXC 执行 docker logs --tail 100 qbittorrent docker exec qbittorrent ls -ld /vuetorrent /vuetorrent/public -
打开原 WebUI,在 设置 → Web UI → 使用备用 Web UI(Use alternative WebUI) 中勾选启用,文件位置填写
/vuetorrent,保存后刷新页面。
这里填写的是容器内目录 /vuetorrent,其下应包含 public;不要填写宿主机目录,也不要填成 /vuetorrent/public。登录仍使用原 qBittorrent 账号,访问端口仍为 8080,已有任务和下载目录继续沿用。
Mod 由容器启动流程安装,后续重建要保留 DOCKER_MODS,并确保能访问镜像与发布资源。latest 会随版本更新,需要固定或回退时,从该 Mod 的包页面选择已发布标签,替换变量中的 latest。它与 qBittorrent 镜像是两项独立版本,更新前一起记录。
调整列表与检查效果
进入 VueTorrent 设置,找到 Pagination Size,先选有限的每页条数,例如界面提供的 50 或 100 条。大量任务时先用分页检查列表响应,再按需要切换无限滚动。刷新页面后核对任务总数、分类、标签与保存路径,并尝试筛选、翻页以及暂停、恢复一个测试任务。
换 UI 后,第七节 Homepage 的组件仍使用 type: qbittorrent,API 地址和凭据保持原值。VueTorrent 通过同一个 qBittorrent Web API 管理任务,无需另开一个服务端口或重接监控,见 项目说明。
恢复原版界面
界面仍可操作时,在设置中取消“使用备用 Web UI”,保存并刷新即可。若填错路径后出现空白页或 Unacceptable file type,在 Docker LXC 停止容器,再编辑持久化配置,避免运行中的进程覆盖修改:
bash1234docker stop qbittorrent cp -p /srv/appdata/qbittorrent/config/qBittorrent/qBittorrent.conf \ /srv/appdata/qbittorrent/config/qBittorrent/qBittorrent.conf.before-ui-recovery vi /srv/appdata/qbittorrent/config/qBittorrent/qBittorrent.conf
在配置文件中搜索 AlternativeUIEnabled,把已有项改为 false,保留它所在的段落。采用旧配置结构的版本(如 5.1.2)位于 [Preferences]:
ini12[Preferences] WebUI\AlternativeUIEnabled=false
若当前版本已将 WebUI 设置独立保存为 [WebUI] 段,则修改该段的 AlternativeUIEnabled=false。只修改现有项,不要在另一段重复添加。随后启动容器,并强制刷新浏览器:
bash1docker start qbittorrent
确认原版界面恢复后,如果不再使用 VueTorrent,再从 Portainer 删除对应的 Mod 配置并重建;只删除 Mod 而保留“备用 Web UI”开关,会使 qBittorrent 继续寻找原来的页面目录。
五、已有配置与任务迁移
已有实例迁入时,保留原应用版本和容器内保存路径。下载文件留在 NAS,复制本地配置及任务记录。
- 在原实例暂停任务并停止容器,让配置落盘。
- 查看原容器 Mounts,记录
/config及其子目录是否存在独立挂载。 - 在旧 Docker 主机保存配置。以下示例适用于整个配置可从容器
/config读取的实例:
bash1234mkdir -p ./qbittorrent-backup/config docker stop qbittorrent docker cp qbittorrent:/config/. ./qbittorrent-backup/config/ tar -czf qbittorrent-config.tar.gz -C qbittorrent-backup config
如果原实例像当前机器一样,/config 为匿名 volume、/config/qBittorrent 又绑定本地目录,分别保存两处挂载源,并将子目录内容合并到导出的 config/qBittorrent。可先通过下列命令取得 volume 名和 bind 来源:
bash1docker inspect --format '{{range .Mounts}}{{println .Type .Name .Source "->" .Destination}}{{end}}' qbittorrent
- 将备份文件传到新 Docker LXC。停止新容器,将导出的 config 内容放入
/srv/appdata/qbittorrent/config,再设置属主1000:1000。 - 在 Portainer 中保持原容器内数据路径。例如原任务使用
/data/downloads,就将新 LXC 的/mnt/nas/downloads映射到/data/downloads。 - 启动新实例,检查任务数量、保存路径、分类和 Tracker 配置。先校验一项任务,确认识别已有文件后再恢复其余任务。
复制配置时保存整个目录,包括任务元数据。原有 BT_backup 中的种子与 fastresume 文件属于任务状态的一部分。
六、开机挂载与故障恢复
NAS 启动慢时,Docker 可能先把本地空目录挂入容器,表现为 qBittorrent 正常运行但找不到文件。恢复时先停止下载容器,待 NAS 就绪后确认 NFS 挂载,再启动应用:
bash1234docker stop qbittorrent mount -a mount | grep ' /mnt/nas/downloads ' ls /mnt/nas/downloads
确认输出中的来源是 QNAP 的 NFS 共享,且原有文件已经出现,再执行:
bash1docker start qbittorrent
基础篇已将 Docker 从 boot 移到 default,并在 /etc/conf.d/docker 中通过 rc_need="netmount" 等待 NFS 挂载。按那一节配置开机顺序;NAS 在运行中掉线、或容器已经绑定了空目录时,仍按本节恢复。挂载命令报错时先处理 NFS,不要继续恢复下载,以免数据写入 LXC 本地盘。
七、接入 Homepage
沿用 NAS 折腾日记(5)Homepage 部署与服务导航 的 Docker 状态代理。在 Homepage 容器的 Env 中设置 HOMEPAGE_VAR_QBIT_USER 和 HOMEPAGE_VAR_QBIT_PASSWORD,使用已经修改并保存的 WebUI 凭据,再重新部署 Homepage。
向 services.yaml 加入下载服务:
yaml12345678910111213- 下载服务: - qBittorrent: href: http://192.168.20.30:8080 siteMonitor: http://192.168.20.30:8080 server: local-docker container: qbittorrent showStats: true widget: type: qbittorrent url: http://192.168.20.30:8080 username: "{{HOMEPAGE_VAR_QBIT_USER}}" password: "{{HOMEPAGE_VAR_QBIT_PASSWORD}}" fields: ["leech", "download", "seed", "upload"]
容器状态来自 Docker,下载与做种任务数、上下行速度来自 qBittorrent Web API。发起前面用于验证的下载任务,再对照 WebUI 与卡片数值。如果返回认证或 Host 错误,检查固定密码、地址和 WebUI 的允许域名设置,保留认证与 Host 校验,只加入实际访问使用的名称。
容器运行和下载速率正常都不能代替 NFS 挂载检查;NAS 空间在 QNAP 卡片查看,任务路径与写入状态仍按第四、六节确认。
八、更新与备份
更新前停止容器并备份本地 config。Portainer 中通过 Duplicate/Edit 设置新镜像,保留环境变量、端口和挂载,重新部署后检查 WebUI、任务列表与文件访问。
bash1234mkdir -p /srv/backups docker stop qbittorrent tar -czf /srv/backups/qbittorrent-config.tar.gz -C /srv/appdata/qbittorrent config docker start qbittorrent
NAS 上的下载文件按原有存储方案保存,本地配置备份用于恢复应用设置和任务状态。
参考
支付宝
微信