mStream 6.32.0 Docker Compose 部署指南
mStream 6.32.0 的 Docker Compose 从 0 到 1 部署实录:镜像选型与拉取降级链、持久化、环境变量、账号预置(PBKDF2 口令与 salt)、升级运维与六类常见问题排障
mStream 6.32.0 Docker Compose 部署指南
目标:本文讲解如何在服务器上用 Docker Compose 从零部署 mStream 6.32.0 音乐流媒体服务,覆盖镜像选型、拉取降级链、持久化、环境变量、账号预置、升级与卸载,全部命令与回显已在 Ubuntu 24.04 实测通过(Compose 项目名 mstream-6.32.0-stack,服务端口 8155,曲库 6 首测试音频)。
一、环境信息
- 操作系统:Ubuntu 24.04(x86_64)
- Docker:24.x / Compose v2(
docker compose子命令形态) - mStream:6.32.0(上游 2026-10-26 发布,部署时 2026-10-29 实查为最新稳定版)
- 镜像:lscr.io/linuxserver/mstream:v6.32.0-ls39(实测镜像体积 1.52 GB)
- Compose 项目名:mstream-6.32.0-stack;服务容器名:mstream-6.32.0-app
- 端口:宿主 8155 → 容器内服务端口 3000
- 数据目录:/srv/mstream/config(配置与数据库)、/srv/mstream/music(曲库)
- 网络:自定义 bridge 网络 mstream-6.32.0-net,网段 10.89.62.0/24
- 演示账号:admin / q1w2e3r4
二、镜像选型说明
mStream 官方提供两种镜像来源:官方 Docker Hub 的 mstream/mstream,以及 LinuxServer.io 维护的 lscr.io/linuxserver/mstream。本文选 LinuxServer.io 镜像,理由有三,均为实测结论:
- 统一的环境变量约定:PUID/PGID/TZ 三个环境变量解决以非 root 用户运行与文件权限问题,与 LinuxServer 全家桶运维习惯一致。
- 转码依赖齐备:镜像内置 ffmpeg 与 essentia 音频分析栈,首启日志实测自动探测成功(
[ffmpeg-bootstrap] Using system ffmpeg: ffmpeg version 8.1.3),无需自行编曲库依赖;这也解释了其 1.52 GB 的体积——用体积换零折腾。 - 版本 tag 明确:
v6.32.0-ls39同时锁定 mStream 版本(6.32.0)与镜像修订(ls39),升级时可精确回退。
官方 mstream/mstream 镜像更小,但转码依赖与音频分析组件需要自行补齐,适合对体积敏感、愿意自建依赖的场景。
⚠️ 镜像拉取降级实录(2026-10-29):
lscr.io直连拉取长时间无进度(卡在层下载);改走 ghcr.io 同源镜像ghcr.io/linuxserver/mstream:v6.32.0-ls39(lscr.io 是 LinuxServer 对 ghcr.io 的代理域名,digest 一致),直连 blob 下载实测仅约 41 KB/s,配置 HTTP 代理后实测提速到约 6.3 MB/s 完成拉取。若两个 registry 都卡,给 Docker daemon 配代理或用代理环境变量拉取即可。当前 ghcr.io 源实测可用。
三、前置条件
- 服务器已安装 Docker(24+)与 Compose v2 插件,验证:
docker compose version
实测输出:
Docker Compose version v2.39.2
- 端口未被占用。规划宿主端口前先用 ss 检查(本文选 8155;此前规划的 8147 已被其他服务占用,实测换端口一次——排障细节见第六章):
ss -ltn | grep ':8155' || echo 'port 8155 free'
实测输出:
port 8155 free
- 曲库目录就绪。没有现成音频时可先用 ffmpeg 生成带标签的测试音频(后续 API 验证都基于它):
mkdir -p /srv/mstream/music /srv/mstream/config
ffmpeg -y -f lavfi -i "sine=frequency=440:duration=30" -f lavfi -i "sine=frequency=660:duration=30" \
-filter_complex "[0:a][1:a]amix=inputs=2" -b:a 128k \
-metadata title="Morning Wave" -metadata artist="Studio Test" \
-metadata album="Signal Garden" -metadata track=1 -metadata date=2026 \
/srv/mstream/music/track01.mp3
实测输出(节选):
Input #0, lavfi, from 'sine=frequency=440:duration=30':
Duration: N/A, start: 0.000000, bitrate: 3072 kb/s
Stream #0:0: Audio: pcm_s16le, 44100 Hz, mono, s16, 705 kb/s
...
size= 479kB time=00:00:29.97 bitrate= 130.9kbits/s speed= 14x
video:0kB audio:474kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.120948%
- (可选)自定义网络网段。若服务器上已有一批 bridge 网络,先确认目标网段空闲:
docker network ls --format '{{.Name}}' | while read n; do docker network inspect "$n" --format '{{range .IPAM.Config}}{{.Subnet}}{{end}} {{.Name}}' 2>/dev/null; done | grep '10\.89\.' | sort
实测输出(节选,本机已占用网段):
10.89.56.0/24 mediamtx-1.21.3-net
10.89.60.0/24 motioneye-0.44.0-net
10.89.61.0/24 mediamtx-1.21.3-stack-net
10.89.62.0/24 空闲,下文采用。
四、部署步骤
4.1 编写 Compose 文件
在 /srv/mstream/ 下创建 docker-compose.yml(已实测完整拉起):
name: mstream-6.32.0-stack
services:
mstream:
image: lscr.io/linuxserver/mstream:v6.32.0-ls39
container_name: mstream-6.32.0-app
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Shanghai
volumes:
- /srv/mstream/config:/config
- /srv/mstream/music:/music
ports:
- "8155:3000"
networks:
mstream-6.32.0-net:
restart: unless-stopped
networks:
mstream-6.32.0-net:
driver: bridge
ipam:
config:
- subnet: 10.89.62.0/24
配置项逐条说明:
name:Compose 项目名,多套环境并存时用于隔离资源命名。container_name:固定容器名,便于后续docker logs/exec直接引用。PUID/PGID:容器内服务进程以宿主 UID/GID 1000 运行,避免曲库文件读写权限问题;TZ使日志时间与本地时区一致。volumes:/config 持久化 config.json、SQLite 数据库、封面、波形缓存与日志;/music 是曲库(可换成自己的音频目录)。ports:宿主 8155 → 容器 3000(mStream 服务进程固定监听 3000,配置文件中的 port 键改了也不影响容器映射,只需保持右侧为 3000)。networks+ipam:固定网段便于防火墙精确放行;不需要网段管控时整个 networks 段可删(Compose 会建默认网络)。restart: unless-stopped:随宿主开机自启(docker 服务启用前提下),手动 stop 后不再自动拉起。
4.2 拉取镜像
cd /srv/mstream && docker compose pull
实测输出(直连 lscr.io 卡住后改走 ghcr.io 同源镜像 + 代理,节选):
v6.32.0-ls39: Pulling from linuxserver/mstream
6e2117088417: Download complete
2203f28f1881: Download complete
9ba80e72bcf9: Download complete
Digest: sha256:8cece50a347d2d1022c73a1e85af4e6e0fbba9a4f9e2f42e2e57ed0e9a58d7cb
Status: Downloaded newer image for ghcr.io/linuxserver/mstream:v6.32.0-ls39
4.3 启动服务
docker compose up -d
实测输出:
[+] Running 2/2
✔ Network mstream-6320-stack_mstream-6.32.0-net Created
✔ Container mstream-6.32.0-app Started
4.4 观察首次启动日志
docker logs mstream-6.32.0-app 2>&1 | tail -25
实测输出(实测首尾,中间为迁移与插件初始化行):
[migrations] started
[migrations] no migrations found
usermod: no changes
User UID: 1000
User GID: 1000
...
2026-10-29T13:41:07.282Z info: Database initialized: /config/db/mstream.db
2026-10-29T13:41:07.302Z info: Checking ffmpeg...
2026-10-29T13:41:07.314Z info: Access mStream locally: http://localhost:3000
2026-10-29T13:41:07.325Z info: [mdns] Advertising _mstream._tcp on 10.89.62.2:3000
2026-10-29T13:41:07.360Z info: [ffmpeg-bootstrap] Using system ffmpeg: ffmpeg version 8.1.3 Copyright (c) 2000-2026 the FFmpeg developers
2026-10-29T13:41:07.361Z info: FFmpeg OK!
Connection to localhost (::1) 3000 port [tcp/*] succeeded!
[ls.io-init] done.
2026-10-29T13:41:12.323Z info: File scan started (Rust) on /music
2026-10-29T13:41:12.325Z info: Scanner using 3 worker thread(s)
2026-10-29T13:41:12.331Z info: Scan complete: 6 files processed, 0 unchanged, 0 stale entries removed, 2 album(s) refreshed, 2 artist(s) refreshed (6 scanned)
2026-10-29T13:41:12.342Z info: Waveform pass complete: 0 generated, 0 failed (0 planned)
2026-10-29T13:41:15.998Z info: Album-art download pass complete: 1 fetched, 0 already-had, 0 not found, 1 error(s) (2 attempted)
关键行解读:Database initialized 表示 SQLite 就绪;FFmpeg OK! 表示转码可用;[ls.io-init] done. 是 LinuxServer 初始化完成标志;随后 Rust 扫描器自动扫描 /music 并接力波形、封面两条增强流水线(封面抓取对无网络封面的专辑报 1 error 属正常,不影响使用)。
4.5 验证服务
探活(未登录访问根路径应跳转登录页):
curl -s -o /dev/null -w 'GET / -> %{http_code} redirect=%{redirect_url}\n' http://localhost:8155/
实测输出:
GET / -> 302 redirect=http://localhost:8155/login
登录页可达且标题正确:
curl -s http://localhost:8155/login/ | grep -oE '<title>[^<]*</title>'
实测输出:
<title>Login</title>
浏览器打开 http://<服务器IP>:8155 即可开始使用:首次部署会进入初始化向导创建管理员;若按 4.6 预置了账号则直接用 admin / q1w2e3r4 登录。
4.6 (可选)预置管理员账号
向导建账号之外,可在启动前预写 /srv/mstream/config/config.json 预置账号。注意 v6.32.0 的口令不是明文:password 必须是 PBKDF2-SHA512(15000 次迭代、32 字节、base64)结果,且每个用户必须携带 base64 盐值 salt。先用 Python 为演示口令生成合规哈希:
python3 -c "
import base64, hashlib
salt = 'k7iA5oyj/jAkEi3KVWYEZQ=='
dk = hashlib.pbkdf2_hmac('sha512', b'q1w2e3r4', salt.encode(), 15000, 32)
print(base64.b64encode(dk).decode())
"
实测输出:
kRwJgrHolLWXdZp4fXOepkx9ODFTsddjYrOeO1uWNlY=
把生成的哈希与盐值写进 config.json 的 users 段(完整字段说明见《mStream 6.32.0 配置参数详解》第五章):
{
"users": {
"admin": {
"password": "kRwJgrHolLWXdZp4fXOepkx9ODFTsddjYrOeO1uWNlY=",
"salt": "k7iA5oyj/jAkEi3KVWYEZQ==",
"admin": true,
"vpaths": ["music"]
}
},
"folders": {
"music": { "root": "/music" }
}
}
写入后重启生效并实测登录 API:
docker compose restart
TOKEN=$(curl -s -X POST http://localhost:8155/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
echo "${TOKEN:0:32}..."
实测输出:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6I...
拿到 token 即预置账号可用。首次写入 config users 后,服务会在启动时把该用户一次性迁移进 SQLite(日志出现 Migrated user: admin),此后以数据库为准。
五、数据持久化说明
mStream 的全部可变数据都落在 /config 与 /music 两个挂载内,备份这两个目录即可完成整机备份:
| 路径(容器内) | 宿主路径 | 内容 | 备份策略 |
|---|---|---|---|
| /config/config.json | /srv/mstream/config/config.json | 全局配置(端口、目录、用户预置段、自动生成的子系统字段) | 变更时备份 |
| /config/db/ | /srv/mstream/config/db/ | SQLite 主库 mstream.db(曲目/用户/播放列表/评分) | 每日增量或快照 |
| /config/album-art/ | /srv/mstream/config/album-art/ | 抓取的专辑封面(内容哈希命名) | 可再生,低优先级 |
| /config/waveform-cache/ | /srv/mstream/config/waveform-cache/ | 播放器波形缓存 | 可再生,可不备份 |
| /config/logs/ | /srv/mstream/config/logs/ | 运行日志(writeLogs 开启时) | 按需轮转 |
| /music/ | /srv/mstream/music/ | 音频原文件 | 与曲库同源,另行备份 |
数据库备份建议在服务停止或空闲时拷贝 mstream.db(SQLite 单文件冷拷贝最稳):
docker compose -f /srv/mstream/docker-compose.yml stop mstream \
&& cp /srv/mstream/config/db/mstream.db /srv/mstream/backup/mstream-$(date +%F).db \
&& docker compose -f /srv/mstream/docker-compose.yml start mstream
实测输出(节选):
Container mstream-6.32.0-app Stopped
Container mstream-6.32.0-app Started
六、环境变量表
| 变量 | 默认值 | 说明 | 实测表现 |
|---|---|---|---|
| PUID | 1000 | 服务进程运行的用户 UID | 日志回显 User UID: 1000,曲库读写无权限问题 |
| PGID | 1000 | 服务进程运行的组 GID | 日志回显 User GID: 1000 |
| TZ | Etc/UTC | 时区 | 设 Asia/Shanghai 后日志时间与本地一致 |
💡 说明:mStream 自身行为(端口、曲库目录、扫描参数等)不在环境变量层控制,一律收敛到 /config/config.json(详见《mStream 6.32.0 配置参数详解》),LinuxServer 环境变量只负责「以谁的身份跑」与「时区」。
七、配置参数说明
首次启动若 /srv/mstream/config 为空,LinuxServer 初始化脚本会自动生成默认 config.json 并进入 Web 初始化向导;若按 4.6 预置了 config.json 则跳过向导。配置体系三句话概括:
- 服务级参数(port、secret、scanOptions、storage、folders、users)写在 config.json,改动后重启生效;
- 扫描与音频分析参数还支持运行时通过管理 API 修改(如
POST /api/v1/admin/db/params/scan-interval),改完自动写回 config.json——实测将 scanInterval 从 1.5 改为 2 后,配置文件中回显"scanInterval": 2; - 子系统字段(iroh.secretKey、dlna.uuid、discovery.mdns.instanceId、federation、setupComplete)由服务首次成功启动时自动生成,无需手写。
config.json 中预置用户的 password/salt 两个键是 v6.32.0 校验的硬性要求,生成方法见 4.6,缺失或格式错误的具体报错见第八章 FAQ。
八、常见问题(FAQ)
Q1:镜像拉取长时间无进度/超时?
现象:docker compose pull 卡在层下载数十分钟无字节增长(2026-10-29 实测 lscr.io 直连如此)。定位:lscr.io 为 LinuxServer 对 ghcr.io 的代理域名,直连链路质量差;改用 ghcr.io/linuxserver/mstream:v6.32.0-ls39 后 digest 一致,但直连 blob 实测仅约 41 KB/s。解决:为 Docker daemon 配置 HTTP 代理后实测约 6.3 MB/s,完成拉取。当前 ghcr.io 源实测可用。
Q2:容器不断重启,日志反复报 salt 校验错误?
现象:预置了 config users 但缺 salt 键时,日志循环输出(实测照抄):
2026-10-29T13:49:22.423Z error: Failed to validate config file
ValidationError: "users.admin.salt" is required
解决:为每个用户补一个 16 字节 base64 盐值(openssl rand -base64 16 生成),password 按第四章 4.6 的 PBKDF2 流程生成,重启后实测恢复正常(GET /login/ 回 200)。
Q3:config 里写了明文口令,登录却报「Passwords do not match」?
现象:password 直接填 q1w2e3r4 明文后,登录日志实测:
warn: Failed login attempt from ::ffff:10.89.62.1. Username: admin
Authentication Error: Passwords do not match
原因:v6.32.0 校验逻辑是把输入口令用用户的 salt 做 PBKDF2-SHA512(15000 次、32 字节)再与存储值比对,存储值必须是哈希而非明文。解决:按 4.6 生成哈希回填。若此前错误数据已入 SQLite,需删除 /srv/mstream/config/db/ 后重启让配置迁移重跑(注意下一个问题)。
Q4:重建数据库后 config 预置用户没生效?
现象:删掉 db 目录重启后日志没有 Migrated user: admin,登录报 user not found。定位:迁移完成标记是 /srv/mstream/config/db/.migrated-from-loki(隐藏文件),rm -rf db/* 不会删除隐藏文件,导致迁移被跳过。解决:连同隐藏文件一起清空(rm -rf /srv/mstream/config/db 整目录删除后重启),实测日志重新出现:
info: Starting migration from LokiJS/config to SQLite...
info: Migrated library: music → /music
info: Migrated user: admin
info: Migration from LokiJS complete
Q5:宿主端口被占用?
现象:docker compose up 报 bind 失败或换端口前探测发现规划端口已监听。实测本文最初规划 8147 时发现已被占用:
$ ss -ltn | grep ':8147'
LISTEN 0 511 0.0.0.0:8147 ...
解决:ss -ltn 重扫空闲端口(本文改用 8155),改 Compose 的 ports 左值后重新 up -d。右侧 3000 永远不变。
Q6:日志出现 Update check failed: Timeout downloading .../manifest.json?
现象:运行期周期性出现该 warn。原因:更新检查需访问 GitHub Releases 的 manifest,网络受限时超时,只影响「有新版本」提示,不影响播放与 API。可忽略,或给服务器出网通道放行 GitHub。
九、等价 docker run
与第四章 Compose 完全等价的单命令形态(不愿用 Compose 时可直跑):
docker run -d \
--name mstream-6.32.0-app \
-p 8155:3000 \
-e PUID=1000 -e PGID=1000 -e TZ=Asia/Shanghai \
-v /srv/mstream/config:/config \
-v /srv/mstream/music:/music \
--restart unless-stopped \
lscr.io/linuxserver/mstream:v6.32.0-ls39
启动后验证与 4.5 相同(curl -s -o /dev/null -w '%{http_code}' http://localhost:8155/ 应得 302)。
十、常用运维命令
状态与日志:
docker compose ps
实测输出:
NAME IMAGE STATUS PORTS
mstream-6.32.0-app lscr.io/linuxserver/mstream:v6.32.0-ls39 Up 12 minutes 0.0.0.0:8155->3000/tcp
docker compose logs -f --tail 50
实测输出(跟踪扫描进度时):
2026-10-29T13:41:12.331Z info: Scan complete: 6 files processed ... (6 scanned)
资源占用:
docker stats --no-stream --format '{{.Name}} CPU={{.CPUPerc}} MEM={{.MemUsage}}' mstream-6.32.0-app
实测输出:
mstream-6.32.0-app CPU=0.10% MEM=55.62MiB / 15.57GiB
重启/停止/卸载:
docker compose restart # 重启服务(改 config.json 后用)
docker compose stop # 停止,保留容器
docker compose down # 停止并删除容器与网络(数据卷在宿主目录,不受影响)
down 实测输出:
[+] Running 2/2
✔ Container mstream-6.32.0-app Removed
✔ Network mstream-6320-stack_mstream-6.32.0-net Removed
升级流程(以未来发布 6.33.0 为例):先改镜像 tag,再拉取重建:
sed -i 's/v6.32.0-ls39/v6.33.0-lsXX/' /srv/mstream/docker-compose.yml
docker compose pull && docker compose up -d
回滚同理把 tag 改回 v6.32.0-ls39。升级前可用程序自带的自检参数验证新版本与现有库兼容(镜像内执行,实测回显):
docker exec mstream-6.32.0-app mstream --boot-probe
实测输出:
boot-probe: ok (module graph)
十一、参考链接
- LinuxServer.io mStream 镜像文档:https://docs.linuxserver.io/images/mstream/
- 镜像源(ghcr.io):https://github.com/linuxserver/docker-mstream/pkgs/container/mstream
- mStream 官方仓库:https://github.com/IrosTheBeggar/mStream
- mStream 官网:http://mstream.io
- 站内延伸:《mStream 6.32.0 介绍与选型指南》、《mStream 6.32.0 配置参数详解》、《mStream 6.32.0 API 使用详解》