Janus 1.4.3 Docker Compose 部署指南
实查镜像生态后以官方源码自建 Janus 1.4.3 镜像,用 Compose 栈(显式项目名 janus-1.4.3-stack)编排部署,覆盖配置卷挂载、端口与 UDP 媒体段映射、API 连通性实测与生产 NAT/鉴权要点。
Janus 1.4.3 Docker Compose 部署指南
目标:用 Docker Compose 把 Janus 1.4.3(全称 janus-gateway,Meetecho 出品的开源 WebRTC SFU 流媒体网关)跑起来:先实查镜像生态并说明为什么选择源码自建镜像,再给出可直接落地的 compose 栈(显式项目名
janus-1.4.3-stack、端口/卷/UDP 媒体段映射),完成配置卷挂载覆盖与 HTTP API 连通性实测。裸机源码安装见《Debian 12 安装 Janus 1.4.3 指南》,组件定位见《Janus 1.4.3 介绍与选型指南》。
一、镜像生态实查:为什么没有现成的 1.4.3 镜像
先说结论:截至 2026-10-26,Docker Hub 上不存在 janus 1.4.3 的预构建镜像,官方也不发布官方镜像。部署 1.4.3 只有两条路:源码自建镜像(本文主路径),或退而求其次用社区镜像的旧版本(1.4.1 及以下)。
实查过程与证据(Docker Hub Registry API,查询日期 2026-10-26):
1. 官方仓库 meetecho/janus-gateway 不提供 Dockerfile。 直接请求仓库根目录的 Dockerfile 原始文件返回 404;官方文档的部署路径只有源码编译与发行版包,从未发布过 meetecho/janus-gateway 镜像。
2. Docker Hub 全景搜索 janus-gateway,按拉取量排序的主流镜像:
| 镜像 | 拉取量 | 版本 tag 现状 | 最后更新 |
|---|---|---|---|
| canyan/janus-gateway | 1,520,744 | 版本 tag 仅 1.1/1.1.4;其余 490 个 tag 为 master_<commit> 快照 | master 快照 2024-05-06,版本 tag 2023-05-20 |
| mwalbeck/janus-gateway | 75,627 | 跟进上游版本线:…1.3.3→1.3→1.4.0→1.4.1(+1/1.4/latest) | 2026-05-02 |
| elice/janus-gateway | 127,947 | 无版本化 tag 说明 | — |
| swmansion/janus-gateway | 7,648 | 最高 1.2.3-0 | 2024-07-22 |
| headwindmdm/janus-gateway | 8,301 | 1.0.0(2025-07)、0.12.3(2022) | — |
3. 逐个探测 1.4.3 相关 tag,全部 404(canyan/janus-gateway:1.4.3、:v1.4.3、:1.4、:1.3.4;mwalbeck/janus-gateway:1.4.3)。
结论:canyan 是拉取量最大的「老牌」镜像但两年多没跟进版本线;mwalbeck 维护最勤(Nextcloud Talk 场景),最新只到 janus 1.4.1。要用 1.4.3(或贴着官方源码),只能在容器里自己编译——好在 Janus 的编译依赖全部来自 Debian 官方仓库,镜像内一次构建即可,下文给出完整可复现的 Dockerfile。
版本折衷方案:如果业务不需要 1.4.3 的修复,
mwalbeck/janus-gateway:1.4.1是当前社区维护最好的现成镜像(同作者还有1/1.4滚动 tag);但 1.x 主线演进很快(multistream 语义在 1.x 内也有变化),本文不建议混用版本写文档,以下全部按 1.4.3 自建走。
二、构建 1.4.3 镜像
2.1 Dockerfile
FROM debian:12
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential pkg-config automake libtool libtool-bin autotools-dev \
gengetopt curl ca-certificates \
libglib2.0-dev libjansson-dev libnice-dev libssl-dev libsrtp2-dev \
libmicrohttpd-dev libwebsockets-dev libusrsctp-dev libsofia-sip-ua-dev \
libopus-dev libogg-dev libcurl4-openssl-dev libconfig-dev \
liblua5.3-dev lua-cjson lua-term \
&& mkdir -p /usr/local/share/pkgconfig \
&& ln -s /usr/lib/x86_64-linux-gnu/pkgconfig/lua5.3.pc /usr/local/share/pkgconfig/lua.pc \
&& rm -rf /var/lib/apt/lists/*
COPY janus-1.4.3.tar.gz dkjson.lua /tmp/
RUN tar xzf /tmp/janus-1.4.3.tar.gz -C /tmp \
&& cd /tmp/janus-gateway-1.4.3 \
&& autoreconf -i \
&& ./configure --prefix=/opt/janus --enable-plugin-lua \
&& make -j$(nproc) \
&& make install \
&& make configs \
&& mkdir -p /opt/janus/share/janus/lua \
&& cp /tmp/dkjson.lua /opt/janus/share/janus/lua/json.lua \
&& rm -rf /tmp/janus*
EXPOSE 8088 8188
CMD ["/opt/janus/bin/janus", "--configs-folder=/opt/janus/etc/janus"]
要点逐条:
- 依赖清单与编译选项与裸机安装完全一致(依据见裸机篇第二节),其中
--enable-plugin-lua必须显式、lua5.3.pc → lua.pc的符号链接必须先mkdir -p目标目录——这两个坑在裸机安装篇已实测记录,镜像内同样会踩。 janus-1.4.3.tar.gz(v1.4.3 release 压缩包)与dkjson.lua预下载进构建上下文再用 COPY 放入,而不是在 RUN 里 curl:构建机直连 GitHub 不稳定时(实测出现过curl: (56) Recv failure: Connection reset by peer,构建层直接失败),预下载一次可以让构建完全可重复,也避免每次重下 6 MB 源码包。tarball 获取:
curl -L -o janus-1.4.3.tar.gz https://codeload.github.com/meetecho/janus-gateway/tar.gz/refs/tags/v1.4.3
curl -L -o dkjson.lua https://raw.githubusercontent.com/LuaDist/dkjson/master/dkjson.lua
cp /tmp/dkjson.lua /opt/janus/share/janus/lua/json.lua:1.4.3 的 Lua 插件脚本require "json",而 Debian 的lua-cjson包注册的模块名是cjson,必须放一份以json为名的纯 Lua JSON 库进 Janus 的脚本目录(原因与报错实录见裸机安装篇 Q2)。- 构建产物约 1.59 GB(单阶段构建保留了编译器与 dev 头文件)。追求体积可改为多阶段构建(编译阶段 + 仅拷贝
/opt/janus与运行时 so 的运行阶段),能压到几百 MB;本文以忠实复现实测为准,不做裁剪。
2.2 构建与结果
docker build -t janus-local:1.4.3 .
实测构建成功后确认(回显):
$ docker image ls janus-local --format "{{.Repository}}:{{.Tag}} {{.Size}}"
janus-local:1.4.3 1.59GB
镜像内版本自证(回显,从运行中的栈容器执行,同一镜像构建期已固化):
$ docker exec janus-1.4.3-web /opt/janus/bin/janus -V
Janus version: 1403 (1.4.3)
Janus commit: not-a-git-repo
Compiled on: Mon Oct 26 06:35:16 UTC 2026
三、Compose 栈编排
目录结构(示例目录 janus-b2/):
janus-b2/
├── Dockerfile
├── janus-1.4.3.tar.gz
├── dkjson.lua
├── compose.yaml
└── conf/ # 从镜像提取的默认配置(覆盖用)
├── janus.jcfg
└── janus.transport.http.jcfg
3.1 compose.yaml
name: janus-1.4.3-stack
services:
janus:
image: janus-local:1.4.3
container_name: janus-1.4.3-web
hostname: janus
ports:
- "8140:8090"
- "8141:8188"
- "21000-21050:21000-21050/udp"
volumes:
- ./conf/janus.jcfg:/opt/janus/etc/janus/janus.jcfg:ro
- ./conf/janus.transport.http.jcfg:/opt/janus/etc/janus/janus.transport.http.jcfg:ro
restart: unless-stopped
说明:
name: janus-1.4.3-stack显式项目名:多套 Janus 或其他组件栈共存时,compose down只会动本项目资源,防止误删别人的栈。实测注意一点——compose 会把项目名里的点规范化掉,实际落盘的项目/网络名是janus-143-stack(docker compose ls可见),语义不受影响。- 端口:宿主 8140 → 容器 8090(HTTP API,8090 是配置覆盖后的端口,见 3.2)、宿主 8141 → 容器 8188(WebSockets)、宿主 21000-21050/UDP → 容器同段(RTP 媒体)。
- 卷:两份配置以只读方式覆盖镜像内默认值,改配置即改文件、
compose restart生效,无需重建镜像。
3.2 从镜像提取默认配置并做最小覆盖
镜像内已带 make configs 生成的全套默认配置。提取两份出来改(docker create + docker cp 不启动容器也能拷文件):
docker create --name janus-cfg-extract janus-local:1.4.3
docker cp janus-cfg-extract:/opt/janus/etc/janus/janus.jcfg conf/janus.jcfg
docker cp janus-cfg-extract:/opt/janus/etc/janus/janus.transport.http.jcfg conf/janus.transport.http.jcfg
docker rm janus-cfg-extract
做两处最小改动,顺便验证「卷覆盖配置」这条链路真实生效:
conf/janus.transport.http.jcfg:port = 8088→port = 8090;conf/janus.jcfg的media段:#rtp_port_range = "20000-40000"→rtp_port_range = "21000-21050"(同时把 compose 的 UDP 映射段对齐到 21000-21050)。
为什么映射 UDP 段要与
rtp_port_range一致?Janus 在配置的 RTP 段内随机落端口收发媒体;映射段比配置段小不影响信令,但媒体可能落在未映射端口上导致「能打通看不到画面」。生产上要么放开整段 20000-40000/udp,要么像本例一样收窄配置段再按段映射。
3.3 启动与首次验证
docker compose up -d
实测启动日志关键行(docker logs janus-1.4.3-web,回显):
Using 172.18.0.2 as local IP...
RTP port range: 21000 -- 21050
Websockets server started (port 8188)...
HTTP webserver started (port 8090, /janus path listener)...
RTP port range: 21000 -- 21050 与 port 8090 证明两份卷挂载配置都已生效(镜像默认值是 20000-40000 与 8088)。
栈状态(回显):
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
janus-1.4.3-web janus-local:1.4.3 "/opt/janus/bin/janu…" janus 41 seconds ago Up 40 seconds 8088/tcp, 0.0.0.0:21000-21050->21000-21050/udp, [::]:21000-21050->21000-21050/udp, 0.0.0.0:8140->8090/tcp, [::]:8140->8090/tcp, 0.0.0.0:8141->8188/tcp, [::]:8141->8188/tcp
宿主侧监听确认(回显):
$ ss -ltn | grep -E ":(8140|8141)"
LISTEN 0 4096 0.0.0.0:8140 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:8141 0.0.0.0:*
LISTEN 0 4096 [::]:8140 [::]:*
LISTEN 0 4096 [::]:8141 [::]:*
3.4 HTTP API 连通性实测
从宿主机穿过端口映射打一次 create(回显):
$ curl -s --max-time 10 -X POST http://127.0.0.1:8140/janus -H "Content-Type: application/json" \
-d '{"janus":"create","transaction":"b2create00001"}'
{"janus":"success","transaction":"b2create00001","data":{"id":5968169530499724}}
返回 success 即「镜像 → 配置 → 网络 → API」全链路打通。完整的 session/handle 消息闭环(attach、message、answer、keepalive、destroy)与报文语义见裸机安装篇第九节,API 不因部署形态变化。
四、日常运维
docker compose ps # 栈状态
docker compose logs -f janus # 跟日志(Janus 日志直接进 stdout,可接 log driver 落盘)
docker compose restart janus # 改配置后重启(conf/ 目录为普通挂载,改完即生效)
docker compose stop # 停栈(保留容器)
docker compose down # 停栈并删容器/网络(conf/ 与 Dockerfile 在宿主目录,不受影响)
升级 1.4.3 → 更新版本:换 tarball 与 tag、重建镜像即可,conf/ 目录中的配置是升级时需要人工 diff 的部分(janus.jcfg.sample 会随版本新增字段):
# 下载新版本 tarball 替换后
docker build -t janus-local:1.4.4 .
# 修改 compose.yaml 的 image 为 janus-local:1.4.4
docker compose up -d
五、生产部署必读:WebRTC 容器化的三个特殊点
普通 Web 服务容器化只需映射 TCP;Janus 这类 WebRTC 服务器多了媒体平面,有三点必须提前规划:
1. ICE 地址与公网映射。 本栈实测日志中 Using 172.18.0.2 as local IP...——这是 compose 内部网络的容器地址,只对本网段有意义。Janus 会把这个地址写进 SDP 候选发给对端;对端在公网时拿到 172.18.0.2 是打不通的。方案:在 janus.jcfg 的 nat 段配置 nat_1_1_mapping = "<公网IP>"(宿主有公网 IP 时),并保持 RTP 段映射完整;K8s/云环境下通常配合 hostNetwork 或 hostPort。
2. UDP 段防火墙。 信令端口(8090/8188)只是控制面;媒体走 rtp_port_range 的 UDP 段。云安全组务必放行,且与 nat_1_1_mapping 配套。
3. 鉴权与证书。 镜像默认配置无鉴权(api_secret 未启用)、DTLS 证书自签。暴露公网前:janus.jcfg 的 general 段启用 api_secret(实测启用后无密请求返回 403,见配置详解篇)、certificates 段挂载正规证书,transport 层启用 https/wss。
六、排障实录
Q1:compose up 报 Bind for 0.0.0.0:20000 failed: port is already allocated?
UDP 端口段被宿主上其他进程/栈占用(本实验环境 20000-20050 已被裸机验证栈占用)。把 rtp_port_range 与 UDP 映射段一起换到空闲段(如本文的 21000-21050)即可。注意 compose 报的端口冲突在「Starting」阶段,容器会进入 Created 状态,改完配置 compose down 后重新 up。
Q2:构建阶段 curl: (56) Recv failure: Connection reset by peer?
构建容器直连 codeload.github.com 被重置(构建机网络出口不稳定)。按 2.1 节改为宿主预下载 + COPY,构建不再依赖外网。
Q3:构建阶段 ln: failed to create symbolic link .../lua.pc: No such file or directory?
/usr/local/share/pkgconfig 目录在 debian:12 基础镜像中不存在,ln -s 前先 mkdir -p。
Q4:容器反复重启,日志报 Lua 插件错误 module 'json' not found?
镜像构建时漏了 cp dkjson.lua .../json.lua 这步(或用了未修复的老镜像)。确认镜像内存在该文件:docker run --rm janus-local:1.4.3 ls /opt/janus/share/janus/lua/。
Q5:API 通但浏览器端连不上/黑屏?
九成是第五节的媒体平面问题:SDP 里的候选地址不可达(nat_1_1_mapping 未配)或 UDP 段未放行。用浏览器 F12 看 WebRTC Internals(chrome://webrtc-internals)的 candidate 状态即可定位。
七、验收清单
-
docker image ls janus-local显示 1.4.3 镜像(约 1.59 GB) -
docker compose ls中项目janus-143-stackrunning(1) - 日志可见
RTP port range: 21000 -- 21050、HTTP webserver started (port 8090, ...)(卷覆盖生效) -
curl http://127.0.0.1:8140/januscreate 返回 success - 生产:
nat_1_1_mapping/防火墙/api_secret/证书四项已按第五节处理
本文镜像构建、compose 编排与全部回显均在实测环境采集(2026-10-26,Docker 28 + Compose v5.6.1),输出为真实回显照录,端口/IP 以你的环境为准。镜像生态数据来自 Docker Hub Registry API(查询日期 2026-10-26)。