端口与网络
YiYi Media 只有两种部署模式:单机版部署(
STANDALONE,三个容器:容器名YiYi-media-standalone/-postgres/-redis,Compose 服务名yiyi-app/postgres/redis) 与分布式部署(DISTRIBUTED,Control/User/Media/Edge 可异机)。这一页以客户部署仓库YiYi-media-deploy各分支根目录的compose.yaml为唯一事实来源(main单机版/v2-all-in-one、v3-multi-host分布式), 给出两套端口视图、放行差异与排查路径。
单机版:对外公开 18080 与 19090
单机版把全部服务进程放进一个应用容器,向宿主机发布两个端口:
| 端口 | 服务 | 位置 | 是否需对外暴露 | 说明 |
|---|---|---|---|---|
18080 | frontend(nginx) | 应用容器 | 是,唯一 Web 入口 | 后台与用户门户都从这里进;容器内 nginx 把 /api/ 与 /mcp 反代到容器内的 127.0.0.1:18086 |
19090 | play-agent | 应用容器 | 是,播放客户端直连 | 内置 Play Agent 的监听端口固定为 19090,容器默认发布到 0.0.0.0:19090。若前面有反代,可用 YIYI_PLAY_AGENT_BIND_HOST=127.0.0.1 收窄 |
18086 | gateway | 应用容器内部 | 否 | API 统一入口与授权执行点,只监听容器内 127.0.0.1:18086 |
18085 | config | 应用容器内部 | 否 | 注册中心 + 节点管理 + 部署能力接口 |
18082 | user | 应用容器内部 | 否 | 账号、会话、配额、播放入口下发 |
18083 | media | 应用容器内部 | 否 | 媒体库、挂载源聚合与协议出口元数据 |
18084 | storage(内置) | 应用容器内部 | 否 | 文件浏览、存储任务;内置 Storage 随主应用升级 |
18088 | license-agent | 应用容器内部 | 否 | 只绑容器内 127.0.0.1:18088,容器外不可达 |
5432 | postgres | 独立容器 | 否 | 只走 Compose 私有网络,不向宿主机发布;应用容器内用 postgres:5432 访问 |
6379 | redis | 独立容器 | 否 | 只走 Compose 私有网络,不向宿主机发布;应用容器内用 redis:6379 访问 |
单机版没有「节点端口」需要放行
单机版固定内置一个 Storage 和一个 Play Agent,用户不需要也不能安装节点。 因此 18084 不需要对任何人开放;19090 已由容器发布到宿主机,播放客户端可直接连, 不需要额外为「节点」开放端口。
放行清单
单机版
需要放行 18080,以及播放客户端要直连时的 19090。 其余端口只存在于应用容器内部。
| 端口 | 方向 | 是否需要放行 | 说明 |
|---|---|---|---|
18080 | 入站(公网) | 是 | Web 入口。若前面套了自己的 HTTPS 反代,则只放行反代的 443,把 18080 收到内网 |
19090 | 入站 | 播放客户端直连时需要 | play-agent 默认绑 0.0.0.0:19090。若改为 YIYI_PLAY_AGENT_BIND_HOST=127.0.0.1 并由宿主机反代,则不必对公网放行 |
5432 / 6379 | 私有网络 | 否 | 只走 Compose 私有网络,不向宿主机发布 |
18082 / 18083 / 18084 / 18085 / 18086 / 18088 | 容器内部 | 否 | 全部只在应用容器内部监听 127.0.0.1,容器外不可达 |
单机版不需要为节点开放任何端口:内置 Storage 与内置 Play Agent 都在同一个容器里, 用户也无法新增外部节点。
分布式版
多台服务器必须位于同一私有网络。除 Web 入口外,私网内还要放行:
| 端口 | 用途 | 访问方向 |
|---|---|---|
5432 | 数据库 | user / media 机 → Control 的 postgres |
6379 | 缓存 | user / media 机 → Control 的 redis |
18085 | 集群通信(注册中心) | user / media / edge 与全部外部工作节点 → Control 的 config |
18089 | 集群许可证同步(Relay,HTTPS) | user / media / edge 的 license-sync → Control 的 license-agent |
外部工作节点自己还要对播放客户端开放 18084(storage)与 19090 起的 play-agent 监听端口。节点安装在别的机器时,节点机必须能访问 Control 的 18085 (注册、心跳、拉取调度任务);若 Storage 节点共用 Control 的 PostgreSQL, 还要能访问 5432。18082(user)与 18083(media)同样要在私网内可达: Control 的 config 与 Edge 的 gateway 都要跨机访问 user。
这些端口绝不可开放到公网
5432、6379、18085、18089 一旦对公网可达,等于把数据库、缓存、注册中心 与许可证分发口全部暴露。云主机上除了宿主机防火墙,还要检查云厂商安全组。 18082、18083、18086 也只应在私网内可达;18088 是每台机器上的授权代理端口, 只绑 127.0.0.1,天然不可跨机。
网络模型:单机版走 Compose 私有网络
单机版的 compose.yaml 只包含 yiyi-app、postgres、redis 三个服务, 三者都接入同一个 Compose 私有网络:
- PostgreSQL、Redis 没有
ports:段,宿主机与公网都不可达。 - 应用容器内各服务通过 Compose 服务名访问基础设施:
postgres:5432、redis:6379。 - 应用容器内的服务互调走
127.0.0.1:<port>(同一容器,共享网络命名空间)。 - 只有前端
18080与 Play Agent19090通过ports:发布;后者默认绑定${YIYI_PLAY_AGENT_BIND_HOST:-0.0.0.0},即播放客户端可直连。
因此 docker port 能看到 yiyi-app 的两个映射,而 postgres、redis 没有映射 —— 这是单机版的设计结果,不是配置疏漏。
不要在单机版 Compose 里给 postgres / redis 加 ports
数据库与缓存不需要被宿主机访问。要调试时可以进容器执行 psql / redis-cli, 不要把端口发布到 0.0.0.0。
分布式版内部角色与本机监听端口
分布式部署由 v2-all-in-one / v3-multi-host 分支的 compose.yaml 维护,control / user / media / edge 是分布式部署内部角色,不是独立部署模式。
| 角色 | 启动的服务 | 本机监听端口 |
|---|---|---|
control | postgres、redis、license-agent、config | 5432、6379(绑本机内网地址)、18085、18088(回环)、18089(集群同步 Relay) |
user | license-sync、user | 18082、18088(回环) |
media | license-sync、media | 18083、18088(回环) |
edge | license-sync、gateway、frontend | 18080、18086、18088(回环) |
外部 Storage 与 Play 节点不由部署包安装,在网页「节点管理」里创建后自助部署, 详见分布式工作节点部署(仅分布式版适用)。
frontend 与 gateway 必须能通过 127.0.0.1:18086 互访
原因是写死的。frontend 的 nginx 配置:
listen 18080;
client_max_body_size 20m;
location / → try_files $uri $uri/ /index.html # SPA fallback
location /api/ → proxy_pass http://127.0.0.1:18086
location = /mcp → proxy_pass http://127.0.0.1:18086上游地址 127.0.0.1:18086 不可配置,因此 nginx 与 gateway 必须处于同一网络命名空间:
- 单机版:两者都在
yiyi-app容器内,天然满足。 - 分布式版:两者都在
edge角色所在的服务器上,不能拆到两台机器。
同一份 nginx 配置里的其他固定行为,排障时会用到:
client_max_body_size 20m:经 Web 入口(/api/)的单个请求体上限 20 MB。文件管理走分片上传,单个请求只带一个分片proxy_request_buffering off,proxy_read_timeout与proxy_send_timeout均为600s- 透传
Host、X-Real-IP、X-Forwarded-For、X-Forwarded-Proto
gateway 的 SERVER_PORT 不能删
gateway 自己的 application.yml 默认 server.port: 18080,与 frontend 的 nginx 撞同一个端口。 部署配置显式注入 SERVER_PORT: "18086" 与 GATEWAY_REGISTRY_PORT: "18086" 才避开冲突。 删掉这两行会让 gateway 抢 18080,或把错误端口注册进注册中心。
play-agent 的「对外端口」与「监听端口」是两个字段
节点管理里 play-agent 有两个端口字段,填错会导致「节点在线但播不了」:
| 字段 | 界面标签 | 含义 | 默认 | 注入的环境变量 |
|---|---|---|---|---|
expectedPort | 对外端口(客户端连接) | 客户端连接用的端口。play-agent 前面有反代时填反代端口(例如 443) | 19090 | 不注入 |
listenPort | 监听端口(进程实际绑定端口) | 进程实际绑定的端口 | 留空按 19090 | PLAY_AGENT_LISTEN=":<端口>" |
关键规则:
- 同一台机器跑多个 play-agent 实例时,每个节点记录必须填不同的监听端口(
19090、19091…),否则第二个实例绑定失败。单机版固定一个内置 Play Agent,不涉及多实例;这一条适用于分布式版。 - 防火墙放行看监听端口。一键安装脚本对 play-agent 取
listenPort(留空按19090),对其他服务取expectedPort。 - 注册到 config 的端口由进程从监听地址自行推断:安装脚本刻意不给 play-agent 注入注册端口与协议,避免把反代的 HTTPS 公网端口当成 HTTP 直连口写进注册信息,否则控制面回访健康检查时会撞上「用 HTTP 请求打了 HTTPS 端口」。
- 配了
node_id时,public_base_url里的地址部分可以省略(进程会向 config 查询自己登记的对外地址),但端口仍按上面的规则处理。 - 「手动反代地址」是另一类节点:不参与部署与升级,只登记反代 IP/域名与端口,系统对它的
/health做心跳检测。
Storage 节点只有一个端口字段(expectedPort,默认 18084,协议默认 http),安装脚本把它注入为 STORAGE_REGISTRY_PORT,注册的健康检查路径固定为 /api/storage/ping。
一键安装脚本还会尝试替你在节点机上放行端口:依次检测 ufw、firewalld、iptables,都没检测到就跳过并提示;默认放行所有来源,执行前 export YIYI_RESTRICT_SOURCE=1 可收紧为只允许控制面地址,export YIYI_OPEN_PORT=0 可完全跳过这一步。云主机还要在云厂商安全组里放行同一个 TCP 端口。
数据库分库
postgres-init.sql 在内置 PostgreSQL 首次初始化(数据目录为空)时执行:
CREATE DATABASE yiyi_config;
CREATE DATABASE yiyi_user;
CREATE DATABASE yiyi_media;
CREATE DATABASE yiyi_storage;它被挂载为 /docker-entrypoint-initdb.d/00-init-yiyi.sql:ro,表结构由各服务启动时的 Flyway 迁移建立。
| 数据库 | 使用方 | 连接串来源 |
|---|---|---|
yiyi_config | config:服务注册表、节点记录、调度任务与执行历史、系统配置 | compose.yaml 拼出 SPRING_DATASOURCE_URL |
yiyi_user | user:账号、会话、配额、注册码与续费码、邀请、活动日志 | 同上 |
yiyi_media | media:媒体库、来源、同步项、聚合项、覆盖、虚拟库、来源访问策略 | 同上 |
yiyi_storage | Storage:挂载源、挂载、存储任务、文件日志、缓存与 spool 状态 | 单机版由统一 PostgreSQL 承载;分布式版由外部 Storage 节点自己的部署配置管理 |
要点:
- 单机版:内置 PostgreSQL 承载全部四个库,应用容器内的服务通过
postgres:5432访问各自的库。首次初始化(数据目录为空)执行postgres-init.sql建四个库。 - 升级旧数据目录时初始化脚本不会重新执行,因此安装脚本会在 PostgreSQL 健康后做幂等存在性检查,只创建缺失的数据库,不覆盖现有库。
- 分布式版:可以把数据库换成外部实例,此时必须预先创建所需数据库并授权连接与建表;
yiyi_storage由外部 Storage 节点自己的部署配置管理。 - PostgreSQL 大版本锁在 16:安装脚本校验
<data>/postgres/PG_VERSION必须是16,镜像为postgres:16.4。
连通性矩阵
服务间地址通过注册中心自动发现,节点只需要知道 config 的地址,不需要手工配置其他 服务的 IP。但网络上必须真的可达。
单机版(全部在容器内部)
| 源 | 目标 | 端口 | 用途 |
|---|---|---|---|
| 浏览器 | frontend | 18080 | 后台、用户门户、网页播放器 |
| frontend 内的 nginx | gateway | 18086(容器内回环) | /api/ 与 /mcp |
| gateway | config | 18085 | 注册与发现 |
| gateway | user | 18082 | 直连上游 |
| config | user | 18082 | YIYI_USER_SERVER_URL |
| config / user / media / storage | postgres | postgres:5432 | 各自的库 |
| user / media | redis | redis:6379 | 会话与缓存 |
| user ↔ media | 对方 | 18083 / 18082 | 优先走注册中心发现 |
| config | license-agent | 18088(容器内回环) | 激活、续租、节点配额 |
| config / user / media / gateway / storage | 本机租约文件 | — | 只读挂载 data/license/lease,本地离线验签 |
| license-agent | 授权中心 | 出网 HTTPS | 拉公钥、激活、续租、占用节点名额 |
| 内置 storage / play-agent | config | 18085(容器内回环) | 注册、心跳、拉取策略 |
| 内置 play-agent | storage | 18084(容器内回环) | 本地磁盘源经 /api/storage/proxy 回源 |
| 宿主机反代 | play-agent | 19090(宿主机回环) | 对播放客户端提供 Emby 出口 |
分布式版(跨主机)
在单机版那套容器内部关系之外,跨主机还需要:
| 源 | 目标 | 端口 | 用途 |
|---|---|---|---|
| 播放客户端 | play-agent(外部节点) | 19090 起 | 播放流直连 |
| 播放客户端 | storage(外部节点) | 18084 | WebDAV 出口 /dav/* |
| user / media / edge 与全部外部工作节点 | Control 的 config | 18085 | 注册、心跳、拉取调度任务 |
| user / media 节点 | Control 的 postgres | 5432 | 各自的库 |
| user / media 节点 | Control 的 redis | 6379 | 会话与缓存 |
| 外部 storage 节点 | postgres | 5432 | yiyi_storage 库 |
| 外部 storage / play-agent 节点 | media / user | 18083 / 18082 | 推送变更、元数据与账号校验 |
常见排查
| 现象 | 先查什么 |
|---|---|
docker port postgres / redis 没有输出 | 正常现象:单机版里数据库与缓存只走 Compose 私有网络,不向宿主机发布 |
install.sh 报「缺少 YIYI_xxx」 | 见环境变量参考的 preflight 清单;.env 里也不能残留 GENERATE_ON_INSTALL 或 example.invalid |
| 页面能开但接口全 502 | gateway 是否与 frontend 处于同一网络命名空间(单机版同在 yiyi-app 内)、18086 是否在监听、SERVER_PORT 是否被改 |
| 容器 healthy 但页面打不开 | 聚合容器的健康检查会校验全部内部服务与两个内置节点;用 docker compose logs yiyi-app 看监管器日志确认是哪个服务未起来 |
gateway 起不来且 18080 被占 | 检查 SERVER_PORT=18086 是否还在部署配置里 |
| 单机版「节点管理」没有新增节点入口 | 设计如此:单机版只能新增手动反代地址,外部节点由分布式版按配额部署 |
API 调 POST /api/config/nodes 返回 403 NODE_CREATION_DISABLED | 设计如此:单机版禁止新增受管节点,只隐藏前端按钮并不构成限制 |
删不掉某个节点(403 SYSTEM_NODE_IMMUTABLE) | 该节点是内置节点,随主应用部署与升级,不能删除、卸载、独立升级或改服务类型 |
| 许可证状态提示版本不匹配 | 部署形态与许可证 Edition 必须一致;单机聚合镜像只接受 STANDALONE,分布式部署只接受 DISTRIBUTED |
| 节点在控制面看不到 / 状态离线 | 节点机能否访问 config:18085(curl http://<control-host>:18085/actuator/health);YIYI_SERVICE_TOKEN 是否与集群一致 |
| 节点在线但播放失败 | play-agent 的对外端口与实际监听端口是否一致;客户端能否直连监听端口;反代是否漏了透传 |
| 分布式节点报数据库连接失败 | Control 的 postgres 是否在私网内可达;私网内 5432 是否放行 |
| 外部节点注册被拒(单机版) | 单机版只接受内置节点身份注册;外部 Storage/Play Agent 实例一律拒绝,历史外置节点不会再进入服务发现 |
| 安装时报「授权公钥缺失」 | install.sh 会去授权中心拉公钥并与镜像内置信任根校验;检查出网 HTTPS 与 YIYI_SERVER_HOST 是否可解析 |
| storage 启动报数据库连接失败 | yiyi_storage 库是否存在;单机版由统一 PostgreSQL 承载四个库,升级旧数据目录时安装脚本会补齐缺失的库 |
| 上传大文件报 413 | 经 Web 入口的请求体受 nginx client_max_body_size 20m 限制 |