plugNmeet 2.5.3 Docker Compose 部署指南
用 Docker Compose 在单台服务器编排 plugNmeet 2.5.3 官方镜像与 LiveKit、NATS、Redis、MariaDB 依赖服务:NKey 生成、配置对位、一键拉起、数据持久化与运维命令,全部实测验证。
plugNmeet 2.5.3 Docker Compose 部署指南
目标:用 Docker Compose 在单台服务器上编排 plugNmeet 2.5.3 官方镜像与 LiveKit、NATS、Redis、MariaDB 四个依赖服务,一次性拉起可用的视频会议栈,实测登录页与健康检查接口正常响应,并给出数据持久化、配置挂载与日常运维命令。
一、环境信息
本文全部命令与回显在下列环境实测取得:
- 操作系统:Ubuntu 24.04 LTS(x86_64),Docker 28.x + Docker Compose v2
- plugNmeet 服务端镜像:
mynaparrot/plugnmeet-server:latest(内含 v2.5.3) - 依赖镜像:
livekit/livekit-server:latest(1.13.x)、nats:2.15-alpine、redis:8-alpine、mariadb:12.3 - Compose 项目名:
plugnmeet-2-5-3-stack(文件顶部name:显式声明) - 自定义网络:
plugnmeet-net(bridge,子网 10.89.64.0/24) - 端口:8145(Web/API)、8146/8147(LiveKit)、50000-60000/UDP(RTC)、4222/8222(NATS)、3306/6379(仅绑定 127.0.0.1)
- 数据目录:
./data/{mariadb,nats,upload,log,artifacts,recordings}(bind mount 持久化)
🔗 组件定位与裸机安装路径见 《plugNmeet 2.5.3 介绍与选型指南》、《Ubuntu 24.04 安装 plugNmeet 2.5.3 指南》。
二、镜像选型说明
| 服务 | 镜像 | 体积 | 选型理由 |
|---|---|---|---|
| plugnmeet | mynaparrot/plugnmeet-server | 1.68GB | 官方唯一镜像,内置客户端静态资源、字体与 FFmpeg 等转换依赖,无需另装 |
| livekit | livekit/livekit-server | 132MB | 官方 SFU,plugNmeet 硬依赖,媒体转发全靠它 |
| nats | nats:2.15-alpine | 42.2MB | plugNmeet v2.x 起用 NATS 承载消息总线与客户端 WebSocket,alpine 变体最小 |
| redis | redis:8-alpine | 161MB | 房间实时状态存储(带 24h TTL 语义),官方默认搭配 |
| mariadb | mariadb:12.3 | 464MB | 历史数据(房间、录制、分析),官方脚本同版本 |
版本对应关系(2026-10-26 实查):服务端 v2.5.3 对应官方编排模板中的 nats:2.15-alpine 与 mariadb:12.3;livekit-server 与 plugnmeet-server 均用 latest 跟随上游,生产环境建议固定到具体 tag。
⚠️ 官方仓已从
plugnmeet/plugnmeet迁移到mynaparrot/plugNmeet-server,旧镜像名在 Docker Hub 已不存在,写编排文件时勿用旧名。
三、前置条件
- 已安装 Docker Engine 与 Compose v2 插件(
docker compose version可用)。 - 端口空闲:8145、8146、8147 未被占用;UDP 50000-60000 防火墙放行。
- 子网规划:compose 自建 bridge 网络需要一段空闲地址。本文选
10.89.64.0/24;多项目共存的宿主机上,10.89.56.0/24起 20 个段常被并行项目占用,遇到Pool overlaps with other one on this address space报错就换一段(见第十一节)。 - 目录准备(本文统一放在
plugnmeet-lab/下):
$ mkdir -p plugnmeet-lab/data/{mariadb,nats,upload,log,artifacts,recordings} plugnmeet-lab/client
$ cd plugnmeet-lab
四、部署步骤
4.1 生成 NATS 密钥(NKey + Curve)
plugNmeet 与 NATS 之间用 auth_callout 鉴权,需要一对用户 NKey、一对账号 NKey(作 issuer)和一对 Curve xkey。用官方 natsio/nats-box 镜像生成(natsio/nats-box:latest 需先 pull):
$ docker run --rm natsio/nats-box:latest nsc generate nkey --user
SUAMHIWAFFCLN3DBPDPWBUMAHBGVPUF6ZIEZ3JKBJAHH6HZYORHDD76EP4
UCQYR5JHAAMHLAO36T7QXCDZOUWBNN2CFN6G5R4JPGAMJFR7VZT325VU
$ docker run --rm natsio/nats-box:latest nsc generate nkey --account
SAAJWLJT6OUHNIZAXI3HT4WQ2TLHTTBXSGV3IZA76N2J6WL4P5FA73ZZTM
ADDCGJ3LS3XP3XJHLIFZP6Q3ASIL64L7DTSQJVBWCDQFWEDZGW3TUZEU
$ docker run --rm natsio/nats-box:latest nsc generate nkey --curve
SXAAJKICFNMG3APQVW23KMOLSO6CPOO7WBLNMQGY7GGT6ZCNLKY4OTPOLA
XBVII36MTEP7BMTG6OFCYWWBAFMLX6CWQOUTD7YKEDJT6JJPI4PVSG44
前缀规则是配对的关键(填反服务必挂,见第十一节第 1 条):
| 类型 | 私钥种子(给 plugnmeet 配置) | 公钥(给 nats-server.conf) |
|---|---|---|
| 用户 NKey | SU 开头 | U 开头 |
| 账号 NKey | SA 开头 | A 开头 |
| Curve xkey | SX 开头 | X 开头 |
本文按上述规则使用一对实测生成的密钥(与你复现时生成的不一致是正常的,全程保持同一对即可):
- 用户:seed
SUAMBUHCVL6ISLATV5RLBIZ5N4TSH5BCJ2XHCHD636PTAOCMXXAR7HLRNY↔ publicUB6MDZLJHLS4YXJMKES6QWWCXCMTDSEZHO5GMYJAUQ3PJDHCTKZ6PGGD - 账号:seed
SAAN4R7SHHPQ7ZSKJWBHACDMSYUGQ2L5QWDVUDCATOHKMSMC2E57KFGQIA↔ publicAC2DMAEHMXUQHIMIUOSRJI7FUN6GKKG55HAMWYO7O2OFWY7GLHXPUWJX - Curve:seed
SXAOPXSEKADPNY7JTT3CNSIRZARFJGFFFXTPRJDXISS4I3GFOFE4B6GFPM↔ publicXCFAO7BHHJUGNY56CYQSCPXA32DASMHOX6WTAGT5RIPGVBZJAZEUJCE6
4.2 四份配置文件
nats-server.conf(公钥填这里):
websocket {
port: 8222
no_tls: true
}
jetstream: {
store_dir: /data/jetstream
}
accounts {
SYS: {
exports: [
{
stream: "$SYS.ACCOUNT.PNM.>",
accounts: [PNM]
}
]
}
PNM: {
jetstream: enabled
imports: [
{
stream: {
account: SYS, subject: "$SYS.ACCOUNT.PNM.>"
}
}
]
users: [
{
nkey: UB6MDZLJHLS4YXJMKES6QWWCXCMTDSEZHO5GMYJAUQ3PJDHCTKZ6PGGD
}
]
}
}
system_account: SYS
authorization {
timeout: 5
auth_callout {
issuer: AC2DMAEHMXUQHIMIUOSRJI7FUN6GKKG55HAMWYO7O2OFWY7GLHXPUWJX
auth_users: [ UB6MDZLJHLS4YXJMKES6QWWCXCMTDSEZHO5GMYJAUQ3PJDHCTKZ6PGGD ]
account: PNM
xkey: XCFAO7BHHJUGNY56CYQSCPXA32DASMHOX6WTAGT5RIPGVBZJAZEUJCE6
}
}
config.yaml(plugNmeet 主配置,私钥种子填在 nats_info):
client:
port: 8145
debug: false
path: "./client/dist"
api_key: APIkey1234567
secret: q1w2e3r4plugnmeetsecret0123456789abcd
token_validity: 10m
webhook_conf:
enable: false
url: ""
enable_for_per_meeting: false
prometheus:
enable: true
metrics_path: "/metrics"
username: ""
password: ""
copyright_conf:
allow_override: false
text: 'Powered by <a href="https://www.plugnmeet.org" target="_blank">plugNmeet</a>'
bbb_join_host: "http://127.0.0.1:8145"
room_default_settings:
max_duration: 0
max_participants: 0
max_num_breakout_rooms: 6
max_preloaded_wb_file_size: 5mb
log_settings:
log_file: "./log/plugNmeet.log"
maxsize: 20
maxbackups: 4
maxage: 2
log_level: "info"
livekit_info:
host: "http://127.0.0.1:8146"
api_key: APIlivekit1234
secret: q1w2e3r4livekitsecret012345678901234
livekit_sip_info:
enabled: false
trunk_name: "pnm-inbound-trunk"
phone_numbers: []
redis_info:
host: localhost:6379
username: ""
password: ""
db: 0
default_ttl: 24h
database_info:
driver_name: mysql
host: localhost
port: 3306
username: plugnmeet
password: q1w2e3r4
db: plugnmeet
prefix: pnm_
charset: "utf8mb4"
loc: "UTC"
conn_max_lifetime: 4m
max_open_conns: 10
nats_info:
nats_urls:
- "nats://127.0.0.1:4222"
nats_ws_urls:
- "ws://127.0.0.1:8222"
account: PNM
nkey: SUAMBUHCVL6ISLATV5RLBIZ5N4TSH5BCJ2XHCHD636PTAOCMXXAR7HLRNY
auth_callout_issuer_private: SAAN4R7SHHPQ7ZSKJWBHACDMSYUGQ2L5QWDVUDCATOHKMSMC2E57KFGQIA
auth_callout_xkey_private: SXAOPXSEKADPNY7JTT3CNSIRZARFJGFFFXTPRJDXISS4I3GFOFE4B6GFPM
num_replicas: 1
room_stream_name: "pnm-room-stream"
default_ttl: 24h
subjects:
system_api_worker: "sysApiWorker"
system_js_worker: "sysJsWorker"
system_core_worker: "sysCoreWorker"
system_public: "sysPublic"
system_private: "sysPrivate"
chat: "chat"
whiteboard: "whiteboard"
data_channel: "dataChannel"
recorder:
recorder_channel: "recorderChannel"
recorder_info_kv: "pnm-recorderInfo"
transcoding_jobs_subject: "pnm-RecorderTranscoderJobs"
upload_file_settings:
path: "./upload"
max_size: 50
max_size_whiteboard_file: 30
keep_forever: false
allowed_types: ["jpg","png","jpeg","svg","pdf","docx","txt","xlsx","pptx","zip","mp4","webm","mp3"]
recorder_info:
recording_files_path: "./recording_files"
token_validity: 30m
ping_timeout: 8s
enable_del_recording_backup: true
del_recording_backup_path: "./recording_files/del_backup"
del_recording_backup_duration: 72h
analytics_settings:
enabled: true
artifacts_settings:
storage_path: "./artifacts"
token_validity: 10m
enable_del_artifacts_backup: true
del_artifacts_backup_path: "./artifacts/trash"
del_artifacts_backup_duration: 72h
insights:
enabled: false
路径解释:
livekit_info.host指向 8146、redis_info.host指向 6379、database_info.host指向 3306,均用localhost——因为 plugnmeet 服务用network_mode: host(见 4.4 编排文件),与 LiveKit/Redis/MariaDB 共享宿主机网络栈,直接回环互通,无需服务名 DNS。全部配置项逐条释义见专栏《plugNmeet 2.5.3 配置参数详解》。
livekit.yaml(keys 与上面 livekit_info 严格一致):
port: 8146
rtc:
port_range_start: 50000
port_range_end: 60000
tcp_port: 8147
use_external_ip: false
allow_tcp_fallback: true
redis:
address: localhost:6379
username: ""
password: ""
db: 0
room:
auto_create: true
enabled_codecs:
- mime: audio/opus
- mime: audio/red
- mime: video/h264
- mime: video/vp8
- mime: video/vp9
- mime: video/av1
logging:
level: info
keys:
APIlivekit1234: q1w2e3r4livekitsecret012345678901234
webhook:
api_key: APIlivekit1234
urls:
- "http://127.0.0.1:8145/webhook"
install.sql:从服务端源码仓库 sql_dump/ 下载(https://raw.githubusercontent.com/mynaparrot/plugNmeet-server/v2.5.3/sql_dump/install.sql),放到编排目录,由 MariaDB 首次初始化自动执行建库建表。
4.3 编排文件 docker-compose.yaml
name: plugnmeet-2-5-3-stack
services:
mariadb:
image: mariadb:12.3
container_name: plugnmeet-v2-5-3-mariadb
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: q1w2e3r4
MARIADB_DATABASE: plugnmeet
MARIADB_USER: plugnmeet
MARIADB_PASSWORD: q1w2e3r4
volumes:
- ./data/mariadb:/var/lib/mysql
- ./install.sql:/docker-entrypoint-initdb.d/install.sql:ro
networks: [pnm]
ports:
- "127.0.0.1:3306:3306"
redis:
image: redis:8-alpine
container_name: plugnmeet-v2-5-3-redis
restart: unless-stopped
networks: [pnm]
ports:
- "127.0.0.1:6379:6379"
nats:
image: nats:2.15-alpine
container_name: plugnmeet-v2-5-3-nats
restart: unless-stopped
command: ["-config", "/nats-server.conf"]
volumes:
- ./nats-server.conf:/nats-server.conf
- ./data/nats:/data/jetstream
networks: [pnm]
ports:
- "127.0.0.1:4222:4222"
- "127.0.0.1:8222:8222"
livekit:
image: livekit/livekit-server:latest
container_name: plugnmeet-v2-5-3-livekit
restart: unless-stopped
network_mode: host
volumes:
- ./livekit.yaml:/app/livekit.yaml:ro
command: ["--config", "/app/livekit.yaml", "--node-ip", "127.0.0.1"]
depends_on:
- redis
plugnmeet:
image: mynaparrot/plugnmeet-server:latest
container_name: plugnmeet-v2-5-3-app
restart: unless-stopped
network_mode: host
depends_on:
- nats
- livekit
- mariadb
- redis
volumes:
- ./config.yaml:/app/config.yaml
- ./client:/app/client
- ./data/upload:/app/upload
- ./data/log:/app/log
- ./data/artifacts:/app/artifacts
- ./data/recordings:/app/recording_files
networks:
pnm:
name: plugnmeet-net
driver: bridge
ipam:
config:
- subnet: 10.89.64.0/24
编排要点:
- 两个网络模式并存:mariadb/redis/nats 走 bridge 隔离、端口只绑
127.0.0.1不暴露公网;livekit/plugnmeet 走network_mode: host——plugNmeet 官方镜像就是 host 网络口径(Web 直挂 8145、UDP 媒体段直收发),这也是官方编排模板的写法。 name: plugnmeet-2-5-3-stack显式声明项目名,docker compose -p不再需要;版本号进名字便于多套并存。- 网络名固定为
plugnmeet-net并显式声明子网,避免重启后网段漂移。
4.4 启动与首次初始化
$ docker compose up -d
Network plugnmeet-net Creating
Network plugnmeet-net Created
Container plugnmeet-v2-5-3-mariadb Creating
Container plugnmeet-v2-5-3-nats Creating
Container plugnmeet-v2-5-3-redis Creating
Container plugnmeet-v2-5-3-nats Created
Container plugnmeet-v2-5-3-mariadb Created
Container plugnmeet-v2-5-3-redis Created
Container plugnmeet-v2-5-3-livekit Creating
Container plugnmeet-v2-5-3-livekit Created
Container plugnmeet-v2-5-3-app Creating
Container plugnmeet-v2-5-3-app Created
Container plugnmeet-v2-5-3-nats Starting
Container plugnmeet-v2-5-3-mariadb Starting
Container plugnmeet-v2-5-3-redis Starting
Container plugnmeet-v2-5-3-nats Started
Container plugnmeet-v2-5-3-mariadb Started
Container plugnmeet-v2-5-3-redis Started
Container plugnmeet-v2-5-3-livekit Starting
Container plugnmeet-v2-5-3-livekit Started
Container plugnmeet-v2-5-3-app Starting
Container plugnmeet-v2-5-3-app Started
首次启动 MariaDB 会执行 install.sql 建库建表(几秒);plugNmeet 启动时自动向 NATS 注册 auth_callout、建 JetStream 流。
4.5 部署验证
$ docker compose ps --format 'table {{.Name}}\t{{.Image}}\t{{.Status}}'
NAME IMAGE STATUS
plugnmeet-v2-5-3-app mynaparrot/plugnmeet-server:latest Up 33 minutes
plugnmeet-v2-5-3-livekit livekit/livekit-server:latest Up 37 minutes
plugnmeet-v2-5-3-mariadb mariadb:12.3 Up 37 minutes
plugnmeet-v2-5-3-nats nats:2.15-alpine Up 33 minutes
plugnmeet-v2-5-3-redis redis:8-alpine Up 37 minutes
$ curl -s -o /dev/null -w 'healthCheck HTTP %{http_code} ' http://127.0.0.1:8145/healthCheck
healthCheck HTTP 200 Healthy
$ docker logs plugnmeet-v2-5-3-app 2>&1 | grep -o 'version: 2.5.3' | head -1
version: 2.5.3
浏览器打开 http://<服务器IP>:8145/(参会入口)与 http://<服务器IP>:8145/login(管理入口,输入 config.yaml 的 api_key/secret)。
五、数据持久化说明
| 宿主机目录 | 容器内路径 | 内容 | 重要性 |
|---|---|---|---|
./data/mariadb | /var/lib/mysql | 房间历史、录制索引、分析记录 | 高(删了历史全没) |
./data/nats | /data/jetstream | JetStream 流(房间实时状态中转) | 中(重建可自动恢复结构) |
./data/upload | /app/upload | 会议中上传的文件 | 高 |
./data/log | /app/log | 服务日志(20MB×4 轮转) | 低 |
./data/artifacts | /app/artifacts | 会后 AI 摘要等产物 | 中 |
./data/recordings | /app/recording_files | 录制文件 | 高 |
全部 bind mount 落宿主机目录,docker compose down 不丢数据;只有 down -v 或手动删目录才会清空。
六、环境变量表
本编排只有 MariaDB 一个服务消费环境变量(其余服务全部走挂载的配置文件),见 4.3 节:
| 变量 | 示例值 | 作用 |
|---|---|---|
MARIADB_ROOT_PASSWORD | q1w2e3r4 | root 口令(仅本地排障用) |
MARIADB_DATABASE | plugnmeet | 首次启动自动建库 |
MARIADB_USER / MARIADB_PASSWORD | plugnmeet / q1w2e3r4 | 业务账号,需与 config.yaml 的 database_info 一致 |
plugNmeet 服务端本身不读环境变量——所有配置集中在 config.yaml,改配置 = 改文件 + docker compose restart plugnmeet。
七、配置参数说明
三份配置的互信对位关系(错一个服务就起不来,全部实测验证):
plugNmeet config.yaml | 对端文件 | 必须一致的字段 |
|---|---|---|
client.api_key / client.secret | 登录页输入 / REST API 双头 | 管理凭证 |
livekit_info.api_key / .secret | livekit.yaml 的 keys: | LiveKit 互信 |
nats_info.nkey 等(SU/SA/SX 私钥种子) | nats-server.conf 的 U/A/X 公钥 | NATS 鉴权 |
database_info.* | MariaDB 环境变量与库名 | 数据库连接 |
client.port 与容器内监听端口一致(host 网络下即宿主机端口);nats_ws_urls 是浏览器直连 NATS 的 WebSocket 地址(生产环境换 wss://域名/ws 并在反代终结 TLS)。
八、配置文件挂载一览
./config.yaml → /app/config.yaml (plugNmeet 主配置,可写挂载便于热替换)
./client → /app/client (客户端静态资源;官方镜像已内置,可省略)
./livekit.yaml → /app/livekit.yaml:ro (LiveKit 配置)
./nats-server.conf → /nats-server.conf (NATS 配置)
./install.sql → /docker-entrypoint-initdb.d/install.sql:ro(MariaDB 首次建表)
./data/* → 各数据路径 (持久化,见第五节)
注意 client 挂载是可选的:官方镜像内自带客户端资源,只有需要替换自制前端时才挂载;且挂载目录内必须是 dist/ 布局(index.html 所在层)。
九、等价 docker run
以 plugNmeet 主服务为例,编排文件等价于:
$ docker network create --driver bridge --subnet 10.89.64.0/24 plugnmeet-net
$ docker run -d --name plugnmeet-v2-5-3-app \
--network host \
--restart unless-stopped \
-v ./config.yaml:/app/config.yaml \
-v ./client:/app/client \
-v ./data/upload:/app/upload \
-v ./data/log:/app/log \
-v ./data/artifacts:/app/artifacts \
-v ./data/recordings:/app/recording_files \
mynaparrot/plugnmeet-server:latest
其余四个服务同思路(mariadb/redis/nats 加 --network plugnmeet-net 与端口映射,livekit 亦为 host 网络)。多服务编排仍建议始终用 compose 管理。
十、常用运维命令
$ docker compose ps # 五服务状态一览
$ docker compose logs -f plugnmeet # 跟踪主服务日志
$ docker compose restart plugnmeet # 改完 config.yaml 后重启生效
$ docker compose stop # 全栈停机(保留数据)
$ docker compose up -d # 全栈拉起
$ docker compose down # 停机并移除容器与网络(数据目录保留)
$ docker compose pull && docker compose up -d # 升级镜像(升级前备份 ./data)
十一、常见问题
- plugNmeet 反复重启,日志报
failed to create nkey option: nkeys: invalid seed,NATS 报Not a valid public nkey for a user:NKey 公私填反了——config.yaml的nats_info必须填SU/SA/SX开头的私钥种子,nats-server.conf必须填对应U/A/X开头的公钥(本文实测踩坑,见 4.1 前缀规则表)。 up -d报Pool overlaps with other one on this address space:声明的子网已被其他 compose 项目占用。把networks.pnm.ipam.config.subnet换一段空闲地址即可(本文从 10.89.62 → 10.89.64 段实测换过两次)。bind: address already in use:8145/8146/8147 或 3306/6379/4222/8222 有占用者。特别注意上次异常退出残留的端口代理进程,ss -tlnp | grep <端口>找到 PID 后处理再up -d。- NATS 日志
Expected callout user to be a valid public account nkey:auth_callout.issuer必须是A开头的账号公钥而不是SA私钥种子;auth_users里的用户 NKey 同理用U公钥。 - 健康检查 502/拒绝连接:
depends_on只保证启动顺序不保证就绪,MariaDB 初始化期间(首启几秒)plugNmeet 可能连库失败自动重启一轮,等 30 秒再看;持续失败查docker compose logs mariadb确认install.sql执行无误。 - 浏览器打不开页面:host 网络下 8145 直接监听在宿主机,检查防火墙;云服务器还需放行安全组。
十二、参考链接
- 官方服务端镜像:https://hub.docker.com/r/mynaparrot/plugnmeet-server
- 官方编排模板:https://github.com/mynaparrot/plugNmeet-server(
docker-compose_sample.yaml,tag v2.5.3) - LiveKit:https://github.com/livekit/livekit NATS:https://github.com/nats-io/nats-server
- 站内相关文档:《plugNmeet 2.5.3 介绍与选型指南》、《Ubuntu 24.04 安装 plugNmeet 2.5.3 指南》