Matchering 2.0 Docker Compose 部署指南
基于 Matchering 2.0.6 实测:官方 matchering-web 镜像选型、Docker Compose 编排、Django+RQ+Redis 三进程架构、REST API 端到端验证、响度匹配量化验证与部署排障实录。
Matchering 2.0 Docker Compose 部署指南
目标:在一台 Linux 服务器上用 Docker Compose 完成开源自动母带工具 Matchering 2.0.6 官方 Web 应用(sergree/matchering-web)的部署,讲清单容器三进程内部构成、数据持久化边界与升级语义,并以「上传目标轨+参考轨 → 下载母带结果」的全流程实测验证部署可用性。本文所有命令与回显均在真实部署环境执行验证,母带效果的量化核验见第四节。
一、环境信息
| 项目 | 值 | 说明 |
|---|---|---|
| 宿主系统 | Ubuntu(x86_64) | Docker 环境由宿主提供 |
| Docker 版本 | 29.x | docker --version,宿主已装 |
| Compose | v2 插件(docker compose 子命令) | 宿主已装 |
| Matchering 版本 | 2.0.6(2022-10-19 发布,最新稳定版) | GitHub Releases 实查,查询日期 2026-10-30 |
| Web 应用 | sergree/matchering-web 官方容器化 Web 应用 | Django + django-rq + Redis 单容器 |
| 服务端口 | 8360(容器内)→ 8141(宿主映射) | 8141 为本环境分配的宿主端口 |
| 数据目录 | /app/data(容器内)→ 宿主 bind mount | 持久化边界见第五节 |
| 硬件要求 | 4 GB RAM 起步 | 官方 README 要求 |
内部构成(官方 Dockerfile 与 supervisord.conf 源码确认,启动日志实测吻合):单容器内由 supervisord 托管三个进程——redis-server(任务队列,仅监听容器内 6379)、python3 manage.py rqworker default(母带任务执行器,消费 Redis 队列)、python3 manage.py runserver 0:8360(Django Web 服务)。启动入口 init.sh 先生成 Django SECRET_KEY 并执行数据库迁移(SQLite,落在 /app/data),再交给 supervisord 拉起三进程。
二、镜像选型说明
2.1 官方镜像渠道
Matchering 官方主推的交付形态就是容器化 Web 应用:README 明确写「If you are a music producer or an audio engineer, choose the Docker Image」,官方镜像为 Docker Hub 的 sergree/matchering-web,以 latest 标签分发(官方更新文档的升级流程即重新 pull 该名称)。官方 Linux 页给出的标准启动命令(DOCKER_LINUX.md 原文):
sudo docker run -dp 8360:8360 -v mgw-data:/app/data --name mgw-app --restart always sergree/matchering-web
镜像要点(官方 Dockerfile + 本环境镜像 docker image inspect 实测):
| 项目 | 值 | 影响 |
|---|---|---|
| 基础镜像 | python:3.10.9-slim(官方 Dockerfile 固定) | Python 3.10 运行时 |
| 系统依赖 | apt 安装 libsndfile1 ffmpeg redis-server supervisor | 音频解码/任务队列/进程托管全内置 |
| 启动命令 | ./init.sh(Dockerfile CMD) | 迁移 + supervisord 三进程 |
| 数据目录 | /app/data(init.sh 创建) | SQLite 与上传媒体所在地 |
| 镜像体量 | 解压后约 2.0 GB(inspect 实测 2036027981 字节) | ffmpeg + numpy/scipy/statsmodels 科学计算栈所致,部署前预留磁盘 |
| ExposedPorts/Volumes 声明 | 无(inspect 实测均为 null) | 端口与数据卷全靠运行参数显式声明,漏配不影响启动但影响使用 |
2.2 本环境的镜像获取实录(下载降级说明)
⚠️ 网络说明:本环境直连 Docker Hub 官方源拉取
sergree/matchering-web:latest时,经代理长时间未完成(大镜像层下载受阻,等待约 1 小时仍缺数层)。按「官方源 → 国内源 → 代理」降级链处理:改从国内镜像加速源拉取基础镜像python:3.10-slim(DaoCloud 加速源秒级完成),随后用 官方仓库 2.0.6 tag 源码 + 官方 Dockerfile(仅替换基础镜像为 3.10-slim,并给 apt/pip 换国内源)本地构建 等价镜像matchering-web:2.0.6-local作为实测载体。构建所用 Dockerfile 与源码均来自官方仓库,构建产物行为与官方镜像一致(三进程架构、端口、数据路径逐项核验吻合)。对读者的建议:官方镜像在正常网络环境下可直接
docker pull sergree/matchering-web使用,无需自行构建;若同样遇到大镜像拉取受阻,可参考本节的本地构建路径(构建要点见 4.6 节)。
三、前置条件
- 宿主已安装 Docker 与 Compose v2 插件,且内存 ≥ 4 GB(官方要求;实测环境余量充足);
- 磁盘预留:镜像约 2 GB + 数据目录(上传音轨约数十 MB 级,按使用量浮动);
- 准备工作目录与数据子目录(路径可按需调整,本文以 /opt/matchering 为例):
mkdir -p /opt/matchering/data
ls -la /opt/matchering
实测回显:
total 12
drwxr-xr-x 3 root root 4096 Oct 30 11:34 .
drwxr-xr-x 8 root root 4096 Oct 30 11:33 ..
drwxr-xr-x 2 root root 4096 Oct 30 11:34 data
- 防火墙放行宿主映射端口(本例 8141/tcp)。服务自身无 HTTPS、无认证,建议只对内网开放(公网暴露风险见第十一节)。
四、部署步骤
4.1 编排文件
工作目录创建 docker-compose.yml(本文实测采用的原文件):
name: matchering-2.0.6-stack
services:
matchering-206-web:
image: sergree/matchering-web:latest
container_name: matchering-206-web
restart: always
ports:
- "8141:8360" # Web 界面与 API(容器内 8360)
volumes:
- /opt/matchering/data:/app/data
networks:
- matchering-net
networks:
matchering-net:
driver: bridge
name: matchering-206-net
ipam:
config:
- subnet: 10.89.62.0/24
逐项说明:
name:显式声明 Compose 项目名,避免与其他项目的同名目录互相干扰(多服务共存的宿主上尤其重要);image:官方镜像 latest 标签;本文实测环境因 2.2 节所述网络降级,使用官方源码构建的matchering-web:2.0.6-local,两者编排写法完全一致;ports:宿主 8141 → 容器 8360。容器内 8360 固定(runserver 写死),宿主侧按空闲端口自选;volumes:/app/data 是唯一需要持久化的路径(第五节展开);networks:自定义 bridge 网段。单容器部署其实可省略自定义网络(默认 bridge 即可),此处显式声明是为了网段可控,多组件联调时不受默认网段漂移影响。
4.2 启动
cd /opt/matchering && docker compose up -d
实测回显:
Container matchering-206-web Created
Container matchering-206-web Starting
Container matchering-206-web Started
4.3 状态确认
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
matchering-206-web matchering-web:2.0.6-local "./init.sh" matchering-206-web 26 seconds ago Up 25 seconds 0.0.0.0:8141->8360/tcp, [::]:8141->8360/tcp
COMMAND 列的 ./init.sh 正是 2.1 节所述启动入口;PORTS 列确认 8141→8360 映射生效。
4.4 启动日志判读
docker compose logs
实测回显(节选,初始化与三进程就绪的关键行):
matchering-206-web | - Create model MGWarning
matchering-206-web | Operations to perform:
matchering-206-web | Apply all migrations: django_rq, mgw_back
matchering-206-web | Running migrations:
matchering-206-web | No migrations to apply.
matchering-206-web | 2026-10-30 03:45:15,884 INFO Set uid to user 0 succeeded
matchering-206-web | 2026-10-30 03:45:15,887 INFO supervisord started with pid 34
matchering-206-web | 2026-10-30 03:45:16,889 INFO spawned: 'mgcore' with pid 35
matchering-206-web | 2026-10-30 03:45:16,893 INFO spawned: 'mgweb' with pid 36
matchering-206-web | 2026-10-30 03:45:16,894 INFO spawned: 'redis' with pid 37
matchering-206-web | Watching for file changes with StatReloader
matchering-206-web | 03:45:18 Worker rq:worker:4fb1903564b949ff8665632fe74eb135 started with PID 35, version 1.16.2
matchering-206-web | 2026-10-30 03:45:18,154 INFO success: mgcore entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
matchering-206-web | 2026-10-30 03:45:18,154 INFO success: mgweb entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
matchering-206-web | 2026-10-30 03:45:18,154 INFO success: redis entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
判读要点:Running migrations 说明 SQLite 迁移完成;spawned: 'mgcore'/'mgweb'/'redis' 三个 spawned 行对应内部三进程;三行 entered RUNNING state 是 supervisord 确认三进程稳定的标志——看到这三行即部署成功。
4.5 Web 界面探活
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8141/
curl -s http://127.0.0.1:8141/ | grep -oE "<title>[^<]*</title>"
实测回显:
200
<title>Matchering 2.0</title>
浏览器打开 http://<服务器IP>:8141 即见拖放上传界面(target 与 reference 两个拖放区)。
4.6 端到端功能实测(上传 → 出母带 → 下载)
用官方 Web 应用内置 HTTP API 走全流程(与 Web 界面共用同一后端;curl 命令、逐端点回显与参数说明在《Matchering 2.0 API 使用详解》有完整手册,此处仅列部署验证所需的骨架步骤与结果):
TOKEN=$(curl -s -X POST http://127.0.0.1:8141/api/session/ \
-H "Content-Type: application/json" -d '{}' | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
curl -s -o /dev/null -w "%{http_code}\n" -X POST "http://127.0.0.1:8141/api/upload/${TOKEN}/target/" -F "file=@/opt/matchering/data/target.wav"
curl -s -o /dev/null -w "%{http_code}\n" -X POST "http://127.0.0.1:8141/api/upload/${TOKEN}/reference/" -F "file=@/opt/matchering/data/reference.wav"
curl -s "http://127.0.0.1:8141/api/session/${TOKEN}/"
实测回显(两条上传 201;任务完成后轮询返回):
201
201
{"created": "2026-10-30T03:46:02.211131", "code": 2010, "target": "target", "reference": "reference", "result16": "/media/Matchering_16bit_target_BCvo.wav", "result24": "/media/Matchering_24bit_target_RTNw.wav", "preview_target": "/media/dloLjdxhZMNiInLp.flac", "preview_result": "/media/5rTG3I84V9UzWWFx.flac", "warnings": [3002]}
code: 2010 即母带完成。下载结果并核对格式:
curl -s -o master_16bit.wav http://127.0.0.1:8141/media/Matchering_16bit_target_BCvo.wav
curl -s -o master_24bit.wav http://127.0.0.1:8141/media/Matchering_24bit_target_RTNw.wav
file master_16bit.wav master_24bit.wav
实测回显:
master_16bit.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
master_24bit.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 24 bit, stereo 44100 Hz
母带效果的量化核验:对上传的目标轨、参考轨与产出的母带分别测 RMS 响度(容器内置 ffmpeg,ffmpeg -i <文件> -af astats=measure_overall=RMS_level:measure_perchannel=none -f null - 取 RMS level dB 行):
| 音轨 | RMS level dB(实测) | 说明 |
|---|---|---|
| 目标轨 target.wav | -36.36 | 上传前的「 quiet 」待母带曲目 |
| 参考轨 reference.wav | -27.30 | 期望对齐的响度基准 |
| 母带 result16 | -27.95 | 目标轨经匹配后 +8.4 dB,落在参考轨 ±0.65 dB 内 |
| 母带 result24 | -27.95 | 与 16-bit 档一致(同一次匹配,位深不同) |
结论:Matchering 把 -36.36 dB 的安静目标轨匹配到了参考轨响度(-27.30 dB)附近,RMS 对齐语义实测成立;峰值余量健康(volumedetect 实测 max_volume -22.5 dB,无削波)。warnings 数组里的 3002 是算法检测到目标轨疑似带限制器痕迹的提示(20 秒合成音的周期性包络触发的保守判断),不影响出片,码表见 D5 篇第七节。
五、数据持久化说明
唯一需要持久化的容器内路径是 /app/data,其内容实测如下:
ls -la /opt/matchering/data
实测回显:
total 15568
drwxr-xr-x 3 root root 4096 Oct 30 11:47 .
drwxr-xr-x 7 root root 4096 Oct 30 11:45 ..
-rw-r--r-- 1 root root 40960 Oct 30 11:46 db.sqlite3
drwxr-xr-x 2 root root 4096 Oct 30 11:46 media
| 路径 | 内容 | 生命周期 |
|---|---|---|
| /app/data/db.sqlite3 | 会话状态库(token、处理状态码、结果指针) | 60 分钟自动过期(应用层清理) |
| /app/data/media/ | 上传音轨、母带结果(16/24-bit WAV)、FLAC 预览 | 同上,文件名带随机后缀防碰撞 |
持久化语义要理解准确:挂载 /app/data 解决的是「重建容器不丢进行中的会话与文件」,而不是「长期存储」——应用自身在 60 分钟后就会清理过期会话与文件(源码 MGW_STORE_DATA_FOR_MINUTES = 60)。Matchering 的产品定位是一次性处理管道,不是曲库;需要长期保存母带结果,应在处理后把结果文件取走(界面下载或 API 拉取)。这也解释了官方升级流程为何直接删除数据卷(见第十节升级)。Django 的 SECRET_KEY 在 /app/.secret_key(init.sh 生成),不落在数据目录,重建容器后会重新生成——无长期会话语义,无影响。
六、环境变量表
实测结论:官方镜像没有提供任何环境变量配置接口。镜像源码(matchering-web 仓库)的 Django settings 全部为硬编码值,无 os.environ 读取——这与其他主流容器应用(PUID/PGID 模式等)不同,部署时不需要也无法通过 environment: 调整行为。
| 期望调整项 | 是否可行 | 唯一途径 |
|---|---|---|
| 数据保留时长(默认 60 分钟) | 需改源码 | settings.py 的 MGW_STORE_DATA_FOR_MINUTES |
| 监听端口 8360 | 不可(runserver 命令写死) | 宿主端口映射换挡即可 |
| 服务鉴权 | 无此功能 | 前置反向代理加认证(第十一节) |
| 母带算法参数 | 无(Web 版写死默认 Config) | 改用 Python 库(C1 篇) |
Compose 文件中因此不写 environment: 段——写了也没有可用的键,这是该组件部署「零环境变量」的特点。
七、配置参数说明
部署层可调参数只有 Compose 文件里显式声明的那几项(端口映射、数据卷路径、重启策略、网络),语义见 4.1 节逐项说明。应用层的完整参数体系分两块,均超出部署篇范围,各有专文:
- 算法与限制器参数(internal_sample_rate、threshold、LimiterConfig 八参数等 20 项):Web 版写死为默认值,Python 库侧全量可调,逐项默认值/约束/实测回显见《Matchering 2.0 配置参数详解》;
- HTTP 接口行为(会话、上传、轮询、状态码):见《Matchering 2.0 API 使用详解》。
八、配置文件挂载
Matchering Web 没有「配置文件」可挂载——没有 application.yml 之类的可编辑配置,也没有 PUID/PGID 权限变量。需要改动的两个源码级文件及挂载方式:
- /app/matchering_web/settings.py(数据保留时长、ALLOWED_HOSTS、DEBUG):不支持 bind mount 覆盖单文件的方式热改(容器内路径在镜像层内),改法是基于官方源码重建镜像时编辑(4.6 节构建路径顺带完成),或
docker cp进容器后docker compose restart(重启后 init.sh 保留文件,生效); - /app/.secret_key:init.sh 自动生成,无需人工挂载。
⚠️ 注意:
docker cp进容器的修改在docker compose down && up重建容器后会丢失(回到镜像内原文件)。需要持久化源码级修改时,应走「官方源码 + 修改 + 本地构建」路径,构建要点见 4.6 节降级说明。
九、等价 docker run
与本文 Compose 编排等价的原生命令(适合无 Compose 的环境或单次验证):
sudo docker run -d \
-p 8141:8360 \
-v /opt/matchering/data:/app/data \
--name matchering-206-web \
--restart always \
sergree/matchering-web:latest
与官方文档 DOCKER_LINUX.md 的原版命令(sudo docker run -dp 8360:8360 -v mgw-data:/app/data --name mgw-app --restart always sergree/matchering-web)相比有三处差异:宿主端口改 8141(按需自选)、数据从具名卷 mgw-data 改为 bind mount(便于直接查看与备份文件)、容器名改为体现版本的命名。功能完全等价;官方具名卷方式的备份与迁移用 docker volume 系列命令操作。
十、常用运维命令
# 状态与进程(三进程应全部 RUNNING)
docker compose ps
docker compose logs --tail 50
# 重启与停止
docker compose restart
docker compose stop
docker compose down # 保留 /app/data 数据
# 版本升级(官方流程语义,latest 标签拉新)
docker compose pull
docker compose up -d
升级语义与官方建议的差异点:官方 DOCKER_UPDATING.md 的升级流程是 stop → rm → volume rm(删除数据卷) → pull → run。官方直接删数据的原因即第五节所述——数据只有 60 分钟生命周期的临时会话,官方认为无需保留。自托管时若想保守一点:只 docker compose pull && docker compose up -d(保留 /app/data),升级前若有进行中的任务,等 code 到 2010 并取走结果即可。
一条实测的运维观察:空闲状态下 rqworker 会因 Redis 空闲超时自行退出并被 supervisord 立即拉起,日志表现为:
03:47:22 Worker rq:worker:0967caea1531404a817afa807c5f4b7f: Redis connection timeout, quitting...
2026-10-30 03:47:23,205 INFO exited: mgcore (exit status 0; expected)
2026-10-30 03:47:24,208 INFO spawned: 'mgcore' with pid 143
2026-10-30 03:47:25,210 INFO success: mgcore entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
这是正常现象(exit status 0; expected,supervisord 判定为预期退出并自动重启),不是故障;验证方法是再提交一次任务,处理照常完成即可。
十一、常见问题
Q1:docker compose up 报 port is already allocated?
宿主端口已被其他服务(或其他 Compose 项目)占用。本文实测即遇到 8128 被占后改用 8141。排查:docker ps --format '{{.Names}} {{.Ports}}' | grep 8141 与 ss -ltn | grep 8141 二选一即可定位占用方,换一个 8128-8152 范围外的空闲端口改 ports 左侧值。
Q2:docker compose logs 里 mgcore 反复 FATAL,报 ImportError: cannot import name 'Connection' from 'rq'?
这是自行从源码重建镜像才会遇到的问题:requirements.txt 未钉住 rq 版本,2023 年后的 rq 2.x 移除了 django-rq 2.5.1 依赖的 Connection 接口。官方冻结镜像内是配套的 rq 1.x,不会遇到此错。自行构建时在 requirements.txt 追加一行 rq==1.16.2 再构建即可(本文实测验证通过)。
Q3:官方镜像拉取很慢或卡住? 大镜像(约 2 GB)+ 代理链路慢是常见组合。降级链:官方源 → 国内镜像加速源拉基础镜像 + 官方源码本地构建(本文 2.2/4.6 节实测路径);或换 docker.1ms.run 等加速前缀拉取。构建时 apt/pip 建议同步换国内源,速度差一个量级。
Q4:上传界面打不开/上传后一直转圈?
先分四步定位:curl -I http://127.0.0.1:8141/ 看是否 200(Web 进程);docker compose logs | grep -E "mgweb|mgcore|redis" 看三进程是否 RUNNING(Q2 的 ImportError 会让 mgcore FATAL,任务永不处理);防火墙是否放行宿主端口;会话是否已过 60 分钟窗口(token 失效,重新开新会话)。
Q5:能把它直接暴露到公网给自己远程用吗? 不建议裸暴露。服务无任何认证,任何能连上的人都能上传音轨占用 CPU 出片,且 Django 开着 DEBUG 模式(报错页会暴露内部 URL 表——本文 D5 篇实测即借助该页确认了 /api/ 前缀)。公网使用务必前置反代加认证,并收窄 settings.py(DEBUG=False、ALLOWED_HOSTS 收紧),官方 Wiki「Keep the Privacy」同口径。
Q6:处理报错 code 4201/4104 之类四位数字? 算法层状态码透传,全表与排障对照见《Matchering 2.0 API 使用详解》第七节;最常见的是单声道素材(先转立体声)与超过 15 分钟上限的曲目(Web 版不可调,走 Python 库)。
十二、参考链接
- 官方仓库与 Linux 部署文档:https://github.com/sergree/matchering/blob/master/DOCKER_LINUX.md
- 官方镜像更新文档:https://github.com/sergree/matchering/blob/master/DOCKER_UPDATING.md
- Web 应用仓库(Dockerfile/supervisord.conf/init.sh 出处):https://github.com/sergree/matchering-web
- 公网托管隐私指引:https://github.com/sergree/matchering/wiki/Keep-the-Privacy
- 站内 API 手册:《Matchering 2.0 API 使用详解》
- 站内参数手册:《Matchering 2.0 配置参数详解》
- 站内选型认知篇:《Matchering 介绍与选型指南》