SwingMusic 3.0.0 Docker Compose 部署指南

SwingMusic 3.0.0 的 Docker Compose 从 0 到 1 部署实录:官方镜像选型、曲库挂载、三步初始化向导、持久化重建无损验证、环境变量与六类常见问题排障

SwingMusicSwingMusicDockerDocker Compose2026/10/30

SwingMusic 3.0.0 Docker Compose 部署指南

目标:本文讲解如何在服务器上用 Docker Compose 从零部署 SwingMusic 3.0.0 音乐流媒体服务,覆盖镜像选型、曲库挂载、初始化向导、数据持久化、环境变量与升级卸载,全部命令与回显已在 Ubuntu 24.04 实测通过(Compose 项目名 swingmusic-3.0.0-stack,服务端口 8154,曲库 4 首测试音频、2 张专辑、2 位艺术家)。

一、环境信息

  • 操作系统:Ubuntu 24.04(x86_64)
  • Docker:24.x / Compose v2(docker compose 子命令形态)
  • SwingMusic:v3.0.0(上游 2026-06-12 发布,部署时 2026-10-30 实查为最新稳定版)
  • 镜像:ghcr.io/swingmx/swingmusic:v3.0.0(官方发布,实测镜像体积 1.27 GB,内置 ffmpeg 7.1.4)
  • Compose 项目名:swingmusic-3.0.0-stack;服务容器名:swingmusic-3.0.0-app
  • 端口:宿主 8154 → 容器内服务端口 1970
  • 数据目录:/srv/swingmusic/config(配置与数据库)、/srv/swingmusic/music(曲库)
  • 网络:自定义 bridge 网络 swingmusic-3.0.0-net,网段 10.89.62.0/24
  • 演示账号:admin / q1w2e3r4

二、镜像选型说明

SwingMusic 官方(swingmx 组织)从 v3.0.0 起直接发布官方镜像 ghcr.io/swingmx/swingmusic,无第三方打包分叉,本文即选官方镜像,理由有三,均为实测结论:

  1. 官方直出,版本与源码严格对应:镜像 tag 即 SwingMusic 版本号(v3.0.0),digest 可在 GitHub Packages 核对(本文实测 digest sha256:a49155d1809b…);
  2. 开箱即含转码与 Web 资源:实测镜像内置 /usr/bin/ffmpeg(ffmpeg version 7.1.4-0+deb13u1),按需转码无需自行补依赖;Web 客户端资源随镜像分发,首启自动落到配置目录的 client/ 下;
  3. 配置路径约定清晰:镜像内数据目录固定为 /config 挂载点,首启日志实测打印 Data folder: /config/swingmusic,与本文持久化章节一致。

⚠️ 镜像体积说明:1.27 GB 主要来自 Python 运行时 + ffmpeg + 音频分析依赖(mutagen//aprise 等)+ Web 静态资源,属官方打包策略,无精简官方变体;对体积敏感可自行多阶段构建,但需自行保证 ffmpeg 与字体依赖完整。

三、前置条件

  1. 服务器已安装 Docker(24+)与 Compose v2 插件,验证:
docker compose version

实测输出:

Docker Compose version v2.39.2
  1. 端口未被占用。规划宿主端口前先用 ss 检查(本文最初规划 8151,实测该端口已被同机其他服务占用,改用 8154——排障过程见「常见问题」Q1):
ss -ltn | grep -E ':815[0-9] '

实测输出(部署时实测节选,8150–8156 中仅余 8154 空闲可用):

LISTEN 0      4096         0.0.0.0:8150       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8151       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8152       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8153       0.0.0.0:*
LISTEN 0      4096         0.0.0.0:8154       0.0.0.0:*
  1. 曲库目录就绪。没有现成音频时可先用 ffmpeg 生成带 ID3 标签的测试音频(后续向导与检索验证都基于它;ffmpeg 在宿主机或镜像内执行均可,以下为宿主机实测命令):
mkdir -p /srv/swingmusic/music /srv/swingmusic/config
ffmpeg -y -hide_banner -loglevel error -f lavfi -i 'sine=frequency=440:duration=8' \
  -af 'afade=t=in:d=1,afade=t=out:st=7:d=1' -codec:a libmp3lame -b:a 192k \
  -metadata 'title=Salt Air' -metadata 'artist=Blue Harbor' \
  -metadata 'album=Tidal Lines' -metadata 'date=2025' -metadata 'genre=Ambient' \
  '/srv/swingmusic/music/Blue Harbor/Tidal Lines/01-Salt Air.mp3'

实测输出(成功时无任何输出,-loglevel error 只报错;用 ls 确认产物):

ls -la '/srv/swingmusic/music/Blue Harbor/Tidal Lines/'

实测输出:

total 416
drwxr-xr-x 2 root root   4096 Oct 30 08:52 .
drwxr-xr-x 3 root root   4096 Oct 30 08:52 ..
-rw-r--r-- 1 root root 193902 Oct 30 08:52 01-Salt Air.mp3

本文曲库共准备 4 首测试音频:Blue Harbor《Tidal Lines》2 首(Salt Air、Sea Glass)+ 秋日山道《晨雾专辑》2 首(晨雾、山间电车),覆盖中英文目录名与多专辑多艺术家场景。

  1. (可选)自定义网络网段。若服务器上已有一批 bridge 网络,先确认目标网段空闲(本文选 10.89.62.0/24):
docker network ls --format '{{.Name}}' | grep 10.89 || echo 'no custom net matching'

四、部署步骤

4.1 编写 Compose 文件

在 /srv/swingmusic/ 下创建 docker-compose.yml(已实测完整拉起):

name: swingmusic-3.0.0-stack

services:
  swingmusic:
    image: ghcr.io/swingmx/swingmusic:v3.0.0
    container_name: swingmusic-3.0.0-app
    ports:
      - "8154:1970"
    volumes:
      - /srv/swingmusic/music:/music
      - /srv/swingmusic/config:/config
    environment:
      - SWINGMUSIC_PORT=1970
      - SWINGMUSIC_DEVICE_NAME=swingmusic-lab
    networks:
      default:
        ipv4_address: 10.89.62.10
    restart: unless-stopped

networks:
  default:
    name: swingmusic-3.0.0-net
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.62.0/24

配置项逐条说明:

  • name:Compose 项目名,多套环境并存时用于隔离资源命名;
  • container_name:固定服务容器名,便于后续 docker logs/exec 直接引用;
  • ports:宿主 8154 → 容器 1970(SwingMusic 固定监听 1970,由镜像内 SWINGMUSIC_PORT 控制;改端口时保持右侧与之一致即可);
  • volumes:/config 持久化配置文件、双 SQLite 库、封面与艺术家图片、Web 客户端资源与插件;/music 是曲库(换成自己的音频目录时,注意下方 4.4 向导里的目录路径以容器内为准);
  • environment:SWINGMUSIC_PORT 与 ports 右值对应;SWINGMUSIC_DEVICE_NAME 是设备名,用于移动 App 配对与许可设备标识;
  • networks + ipam:固定网段便于防火墙精确放行;不需要网段管控时整个 networks 段可删(Compose 会自动建默认网络),ipv4_address 同理可去;
  • restart: unless-stopped:随宿主开机自启(docker 服务启用前提下),手动 stop 后不再自动拉起。

4.2 拉取镜像

docker pull ghcr.io/swingmx/swingmusic:v3.0.0

实测输出(官方源直连可用,无需代理;重复拉取时回显如下):

v3.0.0: Pulling from swingmx/swingmusic
Digest: sha256:a49155d1809bc6ad09d87d76cc91648c149fc80146b5e10260e70fe1cfa78175
Status: Image is up to date for ghcr.io/swingmx/swingmusic:v3.0.0

4.3 启动服务

cd /srv/swingmusic && docker compose up -d

实测输出:

[+] Running 2/2
 ✔ Network swingmusic-3.0.0-net  Created
 ✔ Container swingmusic-3.0.0-app  Started

4.4 观察首次启动日志

docker logs swingmusic-3.0.0-app 2>&1 | head -25

实测输出(首启扫描 3 首测试音频时):

[95mSwing Music v3.0.0 (PID: 1) [0m
Server running on:

[92mhttp://0.0.0.0:1970[0m
[92mhttp://127.0.0.1:1970[0m

[93mData folder: /config/swingmusic[0m

[INFO] Websockets are not supported on WSGI, ignoring
[INFO] Starting granian (main PID: 1)
[INFO] Listening at: http://0.0.0.0:1970
[INFO] Spawning worker-1 with PID: 8
Loading tracks... Done!
Loading albums... Done!
Loading artists... Done!
[INFO] Started worker-1
INFO|Batch 1/1 ...
Completed batch 1/1: 3 files indexed
3 new files indexed
Done

关键行解读:Data folder: /config/swingmusic 确认配置落点与挂载一致;Starting granian 是实际承载 HTTP 的 WSGI 服务器;Completed batch 1/1: 3 files indexed 是首个扫描批次的入库结果(本文曲库初版 3 首,后续增量验证见 4.7)。日志开头的 Assets dir could not be found 为无害告警,不影响功能。

4.5 初始化向导(首次部署必经)

浏览器打开 http://<服务器IP>:8154,首次部署会进入三步初始化向导:

  1. 创建管理员:设置管理员用户名与密码(本文用 admin / q1w2e3r4),对应后端接口 POST /auth/profile/create;
  2. 选择曲库目录:向导列出容器内可挂载的目录,勾选 /music(对应接口 POST /notsettings/add-root-dirs,提交后自动触发全量扫描);
  3. 等待扫描完成:向导轮询初始化状态接口直至扫描批次清零。

向导进度可通过状态接口随时核对(免登录可达):

curl -s http://localhost:8154/onboarding-data

实测输出(向导完成后):

{"adminExists":true,"onboardingComplete":true,"rootDirsSet":true,"scanMessage":"","userHome":"/music"}

字段解读:adminExists 管理员已创建;rootDirsSet 曲库根目录已设置;onboardingComplete 向导整体完成;scanMessage 显示当前扫描批次进度(扫描中形如 scan_batch_cleared: 1/1,完成后清空)。向导完成后刷新页面即进入登录页,用 admin / q1w2e3r4 登录。

4.6 验证服务

探活:

curl -s -o /dev/null -w 'GET / -> %{http_code}\n' http://localhost:8154/

实测输出:

GET / -> 200

登录并确认曲库入库(4 首测试音频、2 张专辑):

curl -s -X POST http://localhost:8154/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"q1w2e3r4"}' -c /tmp/sm-ck.txt -o /dev/null -w 'login -> %{http_code}\n'
curl -s -b /tmp/sm-ck.txt 'http://localhost:8154/getall/albums?start=0' \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print('albums:', d['total'], [i['title'] for i in d['items']])"

实测输出:

login -> 200
albums: 2 ['Tidal Lines', '晨雾专辑']

4.7 (验证)新增曲目与增量扫描

部署完放新歌不需要重建服务:把音频放进曲库目录后触发一次扫描即可。实测生成第 4 首测试音频后手动触发:

curl -s -b /tmp/sm-ck.txt http://localhost:8154/notsettings/trigger-scan

实测输出:

{"msg":"Scan triggered!"}

随后复查专辑曲目数(Tidal Lines 从 1 首变 2 首,新曲目 Sea Glass 可被检索命中),增量行为逐条实测记录见《SwingMusic 3.0.0 配置参数详解》扫描一节;也可开启周期扫描(enablePeriodicScans)免除手动触发。

五、数据持久化说明

SwingMusic 的全部可变数据都落在 /config 与 /music 两个挂载内,备份这两个目录即可完成整机备份。实测重建服务(down 后重新 up)后配置、账号、曲库数据完整无损:

路径(容器内)宿主路径内容备份策略
/config/swingmusic/settings.json/srv/swingmusic/config/swingmusic/settings.json全部运行参数(曲库目录、扫描、艺术家拆分等)变更时备份
/config/swingmusic/private.key同上目录JWT 签名密钥(serverId 派生),删了会导致全部登录态失效必须随库备份
/config/swingmusic/swingmusic.db(+wal/shm)同上目录曲库元数据库(专辑/艺术家/曲目/文件夹)每日增量或快照
/config/swingmusic/images/同上目录提取的专辑封面与艺术家图片(webp)可再生,低优先级
/config/swingmusic/plugins/、client/同上目录插件配置、Web 客户端静态资源随版本自动更新,可不备份
/music//srv/swingmusic/music/音频原文件与曲库同源,另行备份

数据库备份建议在服务停止或空闲时冷拷贝(SQLite 单文件最稳;wal/shm 两个伴生文件一并拷贝):

cd /srv/swingmusic && docker compose stop swingmusic \
  && cp -a config/swingmusic/swingmusic.db* backup/ \
  && docker compose start swingmusic

实测输出(节选):

 Container swingmusic-3.0.0-app  Stopped
 Container swingmusic-3.0.0-app  Started

重建无损验证实录:docker compose down 删除容器与网络后重新 up -d,登录接口与曲库列表实测完全一致(albums: 2 ['Tidal Lines', '晨雾专辑']),登录 Cookie 也因 private.key 持久化而继续有效,无需重新登录。

六、环境变量表

变量官方镜像默认说明实测表现
SWINGMUSIC_PORT1970服务监听端口与 ports 右值一致即可,日志回显 http://0.0.0.0:1970
SWINGMUSIC_DEVICE_NAME宿主名派生设备名,用于移动 App 配对与许可设备识别实测设为 swingmusic-lab 后管理接口回显 deviceName: swingmusic-lab
SWINGMUSIC_CONFIG_DIR未设配置目录父路径(镜像内约定用 /config 挂载点)镜像内以 HOME=/music、数据目录 /config/swingmusic 的约定工作,一般无需设置
SWINGMUSIC_CLIENT_DIR未设自定义 Web 客户端资源目录仅自托管前端构建产物时使用

💡 说明:镜像内置了 SWINGMUSIC_IN_DOCKER=1 与 HOME=/music 两个内部变量(实测 env 回显),前者供程序判断部署形态、后者使默认家目录落在曲库挂载点(向导状态接口回显 userHome: /music 即由此而来);两者均无需手动设置。SwingMusic 的业务参数(曲库、扫描、艺术家拆分等)不在环境变量层控制,一律收敛到 settings.json(详见《SwingMusic 3.0.0 配置参数详解》)。

七、配置参数说明

首启后配置落在 /srv/swingmusic/config/swingmusic/settings.json,全部 30 余个键的逐项含义、默认值与改法见《SwingMusic 3.0.0 配置参数详解》。与部署直接相关的三件事:

  1. 曲库目录:settings.json 的 rootDirs 数组(容器内路径),首启用向导设置,后续可在 Web 设置页改,改完自动触发重扫;
  2. 扫描节奏:enablePeriodicScans(默认关)+ scanInterval(默认 10 分钟)+ enableWatchdog(默认关),家庭曲库低频更新场景建议开周期扫描;
  3. 运行时改参:无需重启——Web 设置页的每次修改都会实时写回 settings.json 并按需重建内存索引(实测 scanInterval: 10 等值与文件内容一致)。

八、配置文件挂载

本文只挂载两个目录:/music(曲库,只读使用亦可,SwingMusic 不改写音频文件,仅读元数据与内嵌封面)与 /config(全部可变数据)。若想把 settings.json 纳入版本管理,可再加一行单文件挂载:

    volumes:
      - /srv/swingmusic/music:/music
      - /srv/swingmusic/config:/config

单文件直挂 settings.json 不推荐:首启时该文件尚不存在,目录挂载才能保证首启自动生成。首启后如需以文件方式改参,改完重启生效:

cd /srv/swingmusic && docker compose restart

九、等价 docker run

与第四章 Compose 完全等价的单命令形态(不愿用 Compose 时可直跑):

docker run -d \
  --name swingmusic-3.0.0-app \
  -p 8154:1970 \
  -e SWINGMUSIC_PORT=1970 \
  -e SWINGMUSIC_DEVICE_NAME=swingmusic-lab \
  -v /srv/swingmusic/music:/music \
  -v /srv/swingmusic/config:/config \
  --restart unless-stopped \
  ghcr.io/swingmx/swingmusic:v3.0.0

启动后验证与 4.6 相同(GET / -> 200 即健康)。

十、常用运维命令

状态与日志:

docker compose ps

实测输出:

NAME                  STATUS          PORTS
swingmusic-3.0.0-app  Up 6 seconds    0.0.0.0:8154->1970/tcp, [::]:8154->1970/tcp
docker compose logs -f --tail 30

实测输出(跟踪扫描进度时的关键行):

INFO|Batch 1/1 ...
Completed batch 1/1: 1 files indexed
1 new files indexed
Done

资源占用:

docker stats --no-stream --format '{{.Name}}  CPU={{.CPUPerc}}  MEM={{.MemUsage}}' swingmusic-3.0.0-app

实测输出:

swingmusic-3.0.0-app  CPU=0.13%  MEM=64.5MiB / 15.57GiB

重启/停止/卸载:

docker compose restart   # 重启服务(改 settings.json 后用)
docker compose stop      # 停止,保留容器
docker compose down      # 停止并删除容器与网络(数据在宿主目录,不受影响)

down 实测输出:

[+] Running 2/2
 ✔ Container swingmusic-3.0.0-app  Removed
 ✔ Network swingmusic-3.0.0-net  Removed

升级流程(以未来发布新版本为例):改镜像 tag → 拉取 → 重建:

sed -i 's/v3.0.0/v3.0.1/' /srv/swingmusic/docker-compose.yml
docker compose pull && docker compose up -d

回滚同理把 tag 改回 v3.0.0。升级前后用程序自带参数核对版本(镜像内实测回显):

docker exec swingmusic-3.0.0-app swingmusic --version

实测输出:

swingmusic v3.0.0

忘记管理员密码时,用自带的重置工具(镜像内实测):

docker exec swingmusic-3.0.0-app swingmusic --password-reset

按提示输入用户名与新密码即可,重置后用新密码登录验证。

十一、常见问题(FAQ)

Q1:宿主端口被占用? 现象:docker compose up -d 报 bind 失败,或规划端口探测时发现已监听。实测本文最初规划 8151 时发现已被同机其他服务占用:

LISTEN 0      4096         0.0.0.0:8151       0.0.0.0:*

解决:ss -ltn 重扫空闲端口(本文改用 8154),改 Compose 的 ports 左值后重新 up -d。右侧 1970 永远不变。

Q2:往曲库放了新歌但界面上没有? 现象:文件已拷入 /music,专辑列表不更新。原因:默认 enablePeriodicScans: false 且无看门狗,SwingMusic 不会自动发现新文件。解决:任选其一——Web 设置页点扫描(等价 GET /notsettings/trigger-scan,实测回显 {"msg":"Scan triggered!"});或开周期扫描;或开看门狗。参数含义见《SwingMusic 3.0.0 配置参数详解》扫描一节。

Q3:重建服务后要重新登录吗? 实测不需要:JWT 签名密钥由 settings.json 的 serverId 派生且 private.key 随 /config 持久化,down 后重新 up -d,原登录 Cookie 实测继续可用(登录接口与曲库列表逐项复查一致)。若删除了 /config/swingmusic/private.key 或整个配置目录,则所有登录态失效,需走初始化向导重建。

Q4:首启日志出现 Assets dir could not be found 告警? 无害告警:程序按默认路径找内置资源未命中后改用镜像内约定路径,Web 资源实际落盘 /config/swingmusic/client/(实测目录存在且页面 200),可忽略。

Q5:中文艺术家/专辑目录名会不会扫不出来? 不会。实测含中文目录《秋日山道/晨雾专辑》的 2 首音频完整入库,检索「晨雾」命中(评分 60.87),专辑与艺术家页均正常展示。仅文件系统需支持 UTF-8(主流 Linux 发行版默认即满足)。

Q6:服务端口能改成 80/443 对外吗? 可以但不建议直改:改法是 ports 左值换成宿主 80/443(右值 1970 不动)。生产对外建议前置 Nginx/Caddy 反向代理加 TLS——Web 与 API 均为 HTTP,反向代理层终止 TLS 即可,程序内无需额外配置。

十二、参考链接

  1. 官方仓库:https://github.com/swingmx/swingmusic
  2. 官方镜像:https://github.com/swingmx/swingmusic/pkgs/container/swingmusic (ghcr.io/swingmx/swingmusic)
  3. 一键安装脚本(非部署形态):https://setup.swingmx.com
  4. 发布页:https://github.com/swingmx/swingmusic/releases (v3.0.0,2026-06-12)
  5. 站内延伸:《SwingMusic 3.0.0 介绍与选型指南》、《mStream 6.32.0 Docker Compose 部署指南》、《Navidrome 0.64.2 Docker Compose 部署指南》