CyTube Docker Compose 部署实战

CyTube 3.86.1 零基础部署实录:Compose 双服务编排设计(MariaDB 依赖与健康检查、应用构建三要点)、首次启动自动建表验证、注册站点管理员与 SQL 提权 255、注册频道与直链视频入队、双客户端同步播放铁证(mediaUpdate 逐位一致),附 Invalid Session 域绑定、日志真实路径、conf 目录挂载缺失等六类现场排障。

CyTubeCyTube流媒体自托管2026/10/29

CyTube Docker Compose 部署实战

目标:把上一篇《CyTube 介绍与选型指南》中"看懂了"的 CyTube 真正跑起来。本篇以 CyTube 3.86.1 为例,完整实录从零开始编写部署文件、初始化 MariaDB、注册站点管理员、创建频道、添加视频,再到双客户端同步播放验证与六类典型故障排查的全过程。所有命令与回显均来自真实部署现场,逐行可复现。配置文件的逐参数讲解与日常运维(管理命令、备份恢复、升级)分别见《CyTube 配置参数详解》与《CyTube 常用命令与运维实战(核心篇)》。

一、部署目标与环境

本篇要交付的最终形态是一个两服务编排栈:

项目内容
应用版本CyTube 3.86.1(3.0 分支滚动版,取自 package.json 实查)
数据库MariaDB 11.8,库名 cytube3,字符集 utf8mb4
Web 页面/接口端口8129(映射到应用监听的 8080)
Socket.IO 实时通道端口8130(映射到应用监听的 1337)
部署目录/opt/cytube-lab/stack(编排文件、配置、数据目录集中于此)
站点管理员admin / q1w2e3r4(全局等级 255)
演示频道movie-night(所有者 admin)

💡 技术拓展:CyTube 的两个监听端口分工不同——8080 是 HTTP 服务(页面、账号、频道管理 REST 路由),1337 是 Socket.IO 服务(聊天、播放同步、队列操作全部走这条实时通道)。客户端打开频道页后,浏览器先从 8129 拿到页面,再通过 socketconfig 接口发现 1337 端口并建立 WebSocket 长连接。所以对外映射时这两个端口都要暴露,缺一个频道页就会一直转圈。

二、方案设计与目录规划

为什么选择"源码构建"而不是现成应用包?CyTube 官方没有发布维护良好的应用包制品,官方 Wiki 的标准路径就是"克隆仓库 + npm install"。把这条官方路径原样封装进编排文件,升级时也遵循同一条路径(git pull + 重装依赖),与官方升级指南完全一致。

部署目录规划如下(/opt/cytube-lab/stack/):

/opt/cytube-lab/stack/
├── docker-compose.yml     # 编排定义:mariadb + cytube 两个服务
├── Dockerfile             # CyTube 应用构建脚本(node:20 + ffmpeg)
├── cytube-src/            # 官方仓库 3.0 分支源码(git clone 所得)
├── conf/
│   ├── config.yaml        # 应用主配置(挂载进运行目录)
│   └── prometheus.toml    # 可选:Prometheus 指标暴露配置
├── db/                    # MariaDB 数据目录(挂载到 /var/lib/mysql)
├── chandump/              # 频道快照目录(2.x 遗留路径,3.x 实际走数据库,见第八节)
└── logs/                  # 日志目录(见第八节:3.86.1 实际写运行目录根下的 *.log)

先获取源码并进入部署目录:

mkdir -p /opt/cytube-lab/stack && cd /opt/cytube-lab/stack
git clone -b 3.0 https://github.com/calzoneman/sync cytube-src

💡 技术拓展:git clone -b 3.0 是官方 Wiki 安装指南指定的分支。CyTube 自 2017 年起不再打版本标签发布,3.0 分支就是"当前稳定版",版本号以该分支 package.json 的 version 字段为准。克隆后可用 grep '"version"' cytube-src/package.json 核对,本次实查输出 3.86.1。

三、编写部署文件

3.1 应用构建文件 Dockerfile

以下为实际使用的 Dockerfile 全文:

FROM node:20-bookworm

RUN apt-get update && apt-get install -y --no-install-recommends \
      ffmpeg mariadb-client git curl ca-certificates \
    && rm -rf /var/lib/apt/lists/*

RUN useradd -m -s /bin/bash cytube

COPY --chown=cytube:cytube cytube-src /opt/cytube

USER cytube
WORKDIR /opt/cytube
RUN npm install

EXPOSE 8080 1337
CMD ["node", "index.js"]

三个关键设计解说:

  1. 安装 ffmpeg 与 mariadb-client:前者是直链视频(HTTP 直连的 MP4/WebM 文件)元数据探测的依赖——CyTube 用 ffprobe 读取视频时长/编码后才能全房间同步倒计时;后者用于备份恢复时在应用侧直接导出数据库。
  2. 专用普通用户 cytube 运行:官方 Wiki 明确警告不要以 root 运行;源码模板里另有 setuid 配置段可在 root 启动后降权,本方案直接在构建期切换到普通用户,更干净。
  3. 以非 root 执行 npm install:这是官方指南的强警告——以 root 身份执行 npm install 会跳过 postinstall 脚本,导致源码构建(lib/ 目录)不完整,应用启动即报 Cannot find module '../lib/...' 类错误。Dockerfile 中先 USER cytube 再 RUN npm install,正是规避此坑。

3.2 编排文件 docker-compose.yml

以下为实际使用的编排文件全文(最终形态,含 conf 目录挂载):

name: cytube-3.86.1-stack

services:
  mariadb:
    image: mariadb:11.8
    container_name: cytube-3.86.1-mariadb
    restart: unless-stopped
    environment:
      MARIADB_ROOT_PASSWORD: q1w2e3r4
      MARIADB_DATABASE: cytube3
      MARIADB_USER: cytube3
      MARIADB_PASSWORD: q1w2e3r4
    volumes:
      - ./db:/var/lib/mysql
    networks: [cytube-net]
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 5s
      timeout: 5s
      retries: 20

  cytube:
    build:
      context: .
      dockerfile: Dockerfile
    image: cytube-3.86.1
    container_name: cytube-3.86.1-app
    restart: unless-stopped
    depends_on:
      mariadb:
        condition: service_healthy
    ports:
      - "8129:8080"
      - "8130:1337"
    volumes:
      - ./conf/config.yaml:/opt/cytube/config.yaml
      - ./conf:/opt/cytube/conf
      - ./chandump:/opt/cytube/chandump
      - ./logs:/opt/cytube/logs
    networks: [cytube-net]

networks:
  cytube-net:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.60.0/24

五个关键设计解说:

  1. depends_on + condition: service_healthy:CyTube 首次启动就要连库建表,数据库没就绪就启动应用会直接崩掉。service_healthy 条件确保编排引擎等到 MariaDB 通过健康检查(healthcheck.sh --connect --innodb_initialized)才拉起应用。
  2. MARIADB_DATABASE/USER/PASSWORD 三件套:MariaDB 官方应用包在首次初始化数据目录时自动建库、建号授权,免去手工执行建库 SQL。
  3. ./db:/var/lib/mysql 持久化:数据全部落在宿主 db/ 目录,销毁服务实例不丢用户、频道、播放列表数据。
  4. ./conf/config.yaml 单文件挂载 + ./conf 整目录挂载:前者是主配置 config.yaml 的固定位置;后者让 conf/ 下的可选扩展配置(如 prometheus.toml、email.toml)也能被应用读到(应用固定从 conf/ 目录查找这些文件)。这个"双挂载"是踩坑后补上的——最初只挂了 config.yaml,导致扩展配置怎么放都不生效,详见第八节。
  5. 固定子网 10.89.60.0/24:本实验室有多套自托管栈并存,固定网段避免多套栈之间网段漂移冲突;同时后文 Socket.IO 客户端直连测试时会用到网关地址 10.89.60.1。

3.3 应用主配置 config.yaml

从官方模板裁剪出最小可用配置(完整逐段讲解见《CyTube 配置参数详解》):

mysql:
  server: 'cytube-3.86.1-mariadb'
  port: 3306
  database: 'cytube3'
  user: 'cytube3'
  password: 'q1w2e3r4'
  pool-size: 10

listen:
  - ip: ''
    port: 8080
    http: true
  - ip: ''
    port: 1337
    io: true

http:
  default-port: 8080
  root-domain: 'localhost'
  alt-domains:
    - '127.0.0.1'
  cookie-secret: 'cytube-local-test-2026'
  trust-proxies: ['loopback']

io:
  domain: 'http://localhost'
  default-port: 1337

channel-save-interval: 1

解说两点:

  1. mysql.server 直接写编排内网的服务名 cytube-3.86.1-mariadb——同网络内服务名即主机名,这是服务发现的最简形态。
  2. http.root-domain 与 io.domain 决定登录 Cookie 的绑定域,本实验以 localhost 访问。这个值在真实部署时必须改成你的对外域名,否则只有本机能登录(第八节第一个排障案例就是它的变体)。

四、首次启动与初始化

4.1 构建与拉起

cd /opt/cytube-lab/stack
docker compose up -d --build

首次构建约 3-5 分钟(npm install 阶段最长)。构建完成后查看运行状态:

docker compose ps

实测回显:

NAME                    IMAGE             STATUS                 PORTS
cytube-3.86.1-app       cytube-3.86.1     Up 2 minutes           0.0.0.0:8129->8080/tcp, [::]:8129->8080/tcp, 0.0.0.0:8130->1337/tcp, [::]:8130->1337/tcp
cytube-3.86.1-mariadb   mariadb:11.8      Up 2 minutes (healthy) 3306/tcp

4.2 启动日志与自动初始化

docker logs cytube-3.86.1-app 2>&1 | head -20

实测回显(首启完整日志):

[INFO] config: No camo configuration found, chat images will not be proxied.
[INFO] config: Loaded prometheus configuration from conf/prometheus.toml.  Prometheus listener is ENABLED
[INFO] config: No email configuration found, defaulting to disabled
[INFO] config: No captcha configuration found, defaulting to disabled
[INFO] server: Starting CyTube v3.86.1
[INFO] webserver: Enabled gzip compression
[INFO] main: Opening service socket
[ERROR] google2vtt: Error: ENOENT: no such file or directory, scandir '/opt/cytube/google-drive-subtitles'
[INFO] peertubelist: Updating peertube host list
[INFO] torlist: File /opt/cytube/tor-exit-list.json not found, downloading from https://check.torproject.org/exit-addresses
[ERROR] peertubelist: Failed to initialize peertube host list: Error: connect ECONNREFUSED 31.13.94.7:443
[ERROR] torlist: Unable to load Tor exit list: Error: connect ECONNREFUSED 209.145.54.50:443

启动日志逐行解说:

  • Starting CyTube v3.86.1:版本号确认,与 package.json 一致;
  • Opening service socket:管理命令套接字已开启(运维篇的 bin/admin.js 就走它);
  • 首启时 knex 迁移脚本自动建表,无任何建表日志输出(静默完成),可用数据库客户端验证;
  • 三条 [ERROR] 均为非致命的启动期自检:google2vtt 是 Google Drive 字幕目录(该功能已弃用,可忽略);peertubelist/torlist 是联网更新 PeerTube 主机清单与 Tor 出口节点清单,隔离网络环境下连不上外网所致,不影响核心功能。

验证建表结果:

docker exec cytube-3.86.1-mariadb mariadb -ucytube3 -pq1w2e3r4 cytube3 -e 'show tables;'

实测回显(14 张表全部由首启迁移自动创建):

aliases
banned_channels
channel_bans
channel_data
channel_libraries
channel_ranks
channels
global_bans
media_metadata_cache
meta
password_reset
user_deletion_requests
user_playlists
users

💡 技术拓展:表名本身就是一份功能地图——users/channels 是账号与频道注册表,channel_data 是频道状态快照(播放队列、MOTD、聊天缓冲等,3.x 已从文件存储迁到这里),channel_libraries 是频道媒体库,aliases 是用户改名别名,banned_channels/global_bans 是站点级封禁。3.x 之前频道快照存 chandump/ 目录下的 JSON 文件,官方 Wiki 老文档里"tar 打包 chandump"的备份建议对 3.x 已不适用,备份方案详见《CyTube 常用命令与运维实战(核心篇)》。

此时浏览器打开 http://服务器IP:8129/ 应能看到 CyTube 首页(页脚显示 "CyTube" 与版本信息)。

五、注册站点管理员

5.1 网页注册首个账号

打开 http://服务器IP:8129/register,填写用户名 admin、密码 q1w2e3r4 提交。等价的接口实测(注意:注册页有 CSRF 防护,必须先 GET 拿令牌与 Cookie 再提交表单):

# 第一步:取注册页,拿到 Cookie 与 _csrf 令牌
curl -s -c /tmp/cj-reg.txt http://localhost:8129/register -o /tmp/reg-form.html
CSRF=$(grep -oE 'name="_csrf" value="[^"]*"' /tmp/reg-form.html | head -1 | sed 's/.*value="//;s/"//')

# 第二步:带 Cookie 与令牌提交注册
curl -s -b /tmp/cj-reg.txt -X POST http://localhost:8129/register \
     -d "name=tester01&password=q1w2e3r4&_csrf=$CSRF"

实测回显(注册成功页核心片段):

<div class="alert alert-success messagebox center"><strong>Registration Successful</strong>
  <p>Thanks for registering, tester01!  Now you can <a href="/login">Login</a> to use your account.</p>
</div>

注册成功的账号落库验证:

docker exec cytube-3.86.1-mariadb mariadb -ucytube3 -pq1w2e3r4 cytube3 \
  -e 'select id,name,global_rank from users;'

实测回显:

id	name	global_rank
1	admin	1
2	tester01	1

5.2 SQL 提权为站点管理员

新注册账号 global_rank 只有 1(普通注册用户)。站点管理员(global_rank ≥ 255)无法从界面点出来,官方指南指定的方式就是注册后用 SQL 手工授予:

docker exec cytube-3.86.1-mariadb mariadb -ucytube3 -pq1w2e3r4 cytube3 \
  -e "UPDATE users SET global_rank=255 WHERE name='tester01'; select id,name,global_rank from users;"

实测回显:

id	name	global_rank
1	admin	255
2	tester01	255

💡 技术拓展:CyTube 的等级体系是全站通用的权限标尺——频道内 0=访客、1=注册用户、2=版主、3=频道管理员、4=频道所有者,而 255 是站点管理员(可进站点管理后台 ACP、管理全部频道)。global_rank=255 提权后无需重启,账号重新登录即生效。

六、创建频道与添加视频

6.1 注册频道

登录 admin 账号后,进入 http://服务器IP:8129/account/channels 页面注册频道。接口实测(频道注册同样是"表单 + CSRF + referrer 校验"的三重防护,且必须带 action=new_channel 动作参数):

# 登录(同样先取登录页拿 Cookie/令牌,再提交)
curl -s -c /tmp/cj-login.txt http://localhost:8129/login -o /tmp/lform.html
CSRF=$(grep -oE 'name="_csrf" value="[^"]*"' /tmp/lform.html | head -1 | sed 's/.*value="//;s/"//')
curl -s -b /tmp/cj-login.txt -c /tmp/cj-login.txt -X POST http://localhost:8129/login \
     -d "name=tester01&password=q1w2e3r4&_csrf=$CSRF"
# 回显:Logged in as tester01

# 从频道管理页取新令牌后注册频道 lab-room
CSRF2=$(curl -s -b /tmp/cj-login.txt http://localhost:8129/account/channels \
        | grep -oE 'name="_csrf" value="[^"]*"' | head -1 | sed 's/.*value="//;s/"//')
curl -s -b /tmp/cj-login.txt -X POST http://localhost:8129/account/channels \
     -d "action=new_channel&name=lab-room&_csrf=$CSRF2" -o /dev/null -w '%{http_code}\n'

实测回显:

200

频道落库验证:

docker exec cytube-3.86.1-mariadb mariadb -ucytube3 -pq1w2e3r4 cytube3 \
  -e 'select id,name,owner from channels;'

实测回显:

id	name	owner
1	movie-night	admin
2	lab-room	tester01

频道注册成功后,访问地址形如 http://服务器IP:8129/r/频道名(中间的 r/ 由配置项 channel-path 决定)。实测:

curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8129/r/lab-room

实测回显:

200

6.2 向播放队列添加视频

进入 http://服务器IP:8129/r/movie-night,右侧播放队列下方的媒体输入框粘贴视频链接即可入队。本实验放的是一块自建 HTTPS 站点上的 30 秒 MP4 直链(https://10.89.60.1:8133/cytube-test.mp4,类型 fi = file/直链视频)。

入队动作经 Socket.IO 通道提交,服务端响应实测(Socket.IO 客户端脚本逐帧抓取,事件名与负载原样记录):

[15:42:39][A(admin)] ==> queue {"id":"https://10.89.60.1:8133/cytube-test.mp4","type":"fi","pos":"end","title":"CytubeLab 同步测试片","temp":false}
[15:42:36] [A(admin)] <== playlist: [{"media":{"id":"https://10.89.60.1:8133/cytube-test.mp4","title":"CytubeLab 同步测试片","seconds":30,"duration":"00:30","type":"fi","meta":{"codec":"mov/h264","bitrate":839.586}},...

解说:seconds: 30 / duration: "00:30" 与 meta.codec: mov/h264 是服务端调用 ffprobe 探测直链视频后回填的元数据——这正是 3.1 节 Dockerfile 里必须装 ffmpeg 的原因;缺了它,直链视频入队直接报错。

💡 技术拓展:type 字段是媒体源类型标识,常见取值:yt(YouTube)、vi(Vimeo)、tv(Twitch)、fi(HTTPS 直链文件)、hl(HLS 直播流)、cm(自定义 custom media)。直链必须 HTTPS——浏览器混合内容策略禁止在页面里嵌 HTTP 视频。

七、双客户端同步播放验证

这是部署验收的关键一步:两个"浏览器标签页"(模拟两个观众)同时进频道,验证播放进度由服务端统一钉死。用两个 Socket.IO 客户端分别以 admin(房主)与 viewer(观众)身份接入,抓取同步事件流:

[15:42:36][A(admin)] <== setCurrent: 0
[15:42:36][A(admin)] <== changeMedia: {"id":"https://10.89.60.1:8133/cytube-test.mp4",...,"currentTime":8,"paused":false}
[15:42:38][B(viewer)] <== changeMedia: {"id":"https://10.89.60.1:8133/cytube-test.mp4",...,"currentTime":10.001,"paused":false}
[15:42:41][A(admin)] <== mediaUpdate: {"currentTime":13.001999999999999,"paused":false}
[15:42:41][B(viewer)] <== mediaUpdate: {"currentTime":13.001999999999999,"paused":false}
[15:42:46][A(admin)] <== mediaUpdate: {"currentTime":18.000999999999998,"paused":false}
[15:42:46][B(viewer)] <== mediaUpdate: {"currentTime":18.000999999999998,"paused":false}
[15:42:51][A(admin)] <== mediaUpdate: {"currentTime":23.006,"paused":false}
[15:42:51][B(viewer)] <== mediaUpdate: {"currentTime":23.006,"paused":false}

逐行解读这组"同步铁证":

  1. 后进房的观众直接被拽到当前进度:B 在视频已播 10 秒时进房,服务端立即下发 changeMedia 携带 currentTime: 10.001,从第 10 秒开始看而不是从 0 开始;
  2. 服务器计时器权威广播:两端每 5 秒收到一次 mediaUpdate,且 currentTime 数值完全一致(13.002/18.001/23.006 逐位相同)——这就是"服务器权威同步":客户端只是按服务端时间戳校准本地播放器;
  3. 周期广播间隔由 playlist.update-interval(默认 5 秒)决定,可在配置中调整(改值实测见《CyTube 配置参数详解》)。

八、排障实录

以下六个故障均来自本次部署现场,按"现象 → 定位 → 处置"记录。

8.1 登录报 Invalid Session:Cookie 域绑定与访问域名不一致

现象:注册/登录表单提交返回 403,页面提示:

<h1>Invalid Session</h1>
<p>Your browser attempted to submit form data to <code>/register</code> with an invalid authentication token.  This may be because:

定位:配置中 http.root-domain: 'localhost',登录 Cookie 只对 localhost 域签发。用 127.0.0.1 访问时,服务端不下发 Cookie(实测 curl http://127.0.0.1:8129/register 的响应里没有任何 Set-Cookie),后续带令牌提交自然被 CSRF 中间件拒绝。改用 http://localhost:8129 访问后 Cookie 正常下发,一次成功。

处置:本地实验用 localhost 访问;真实部署把 root-domain、io.domain、alt-domains 三处改成对外域名。教训:Cookie 域绑定是 CyTube 登录体系的第一道门,访问域名必须与配置一致。

8.2 游客登录被限流:Guest logins are restricted

现象:同一台机器 60 秒内第二次以游客身份登录频道,服务端拒绝:

[15:42:37] [B(viewer)] <== login: {"success":false,"error":"Guest logins are restricted to one per IP address per 60 seconds."}

定位:这是配置项 guest-login-delay: 60 的防灌水限流(每 IP 每 60 秒只允许一次游客登录),不是故障。多标签页测试时若第二个客户端要登录,改用注册账号或间隔 60 秒。

8.3 重复入队被拒:This item is already on the playlist

现象:同一链接重复添加到播放队列,服务端拒绝:

[15:42:40] [A(admin)] <== queueFail: {"msg":"This item is already on the playlist","link":"https://10.89.60.1:8133/cytube-test.mp4","id":"https://10.89.60.1:8133/cytube-test.mp4"}

定位:播放队列默认去重(频道设置里的 allow_dupes 开关控制)。按 queueFail 提示换链接或开启频道内允许重复即可。

8.4 启动日志三条 ERROR:peertubelist / torlist / google2vtt

现象:每次启动日志都有三条 [ERROR](见 4.2 节回显),其中两条是 connect ECONNREFUSED。

定位与处置:

  • peertubelist/torlist:CyTube 启动时联网拉取 PeerTube 实例清单(instances.json)与 Tor 出口节点清单,用于媒体链接识别与安全过滤。隔离网络连不上即报错,不影响主功能;若站点不用 PeerTube/Tor 相关特性可长期忽略,能出网的环境重启后会自动拉取成功。
  • google2vtt:扫描 google-drive-subtitles 字幕目录失败。Google Drive 播放支持已在官方层面弃用(见《CyTube 介绍与选型指南》第六节),此目录本就不存在,忽略即可。

结论:这三条是"启动自检噪音",判断应用是否健康应看 Starting CyTube v3.86.1 之后有没有 webserver: Enabled gzip compression、Opening service socket 等核心行,以及端口探活是否 200。

8.5 logs/ 目录一直是空的:日志文件的真实位置

现象:编排里挂载了 ./logs:/opt/cytube/logs,但宿主 logs/ 目录始终为空,而应用日志明显在持续输出。

定位:查 3.86.1 源码 src/logger.js,三个日志文件的落盘路径写死为运行目录根(path.join(__dirname, "..", "error.log")),即 /opt/cytube/ 下而不是 /opt/cytube/logs/:

docker exec cytube-3.86.1-app sh -c 'ls -la /opt/cytube/*.log'

实测回显:

-rw-r--r-- 1 cytube cytube  527 Oct 28 15:45 /opt/cytube/error.log
-rw-r--r-- 1 cytube cytube  142 Oct 28 15:49 /opt/cytube/events.log
-rw-r--r-- 1 cytube cytube   90 Oct 28 15:58 /opt/cytube/http.log
-rw-r--r-- 1 cytube cytube 1666 Oct 28 15:55 /opt/cytube/sys.log

处置:把挂载点从 ./logs:/opt/cytube/logs 改为这四个具体文件(error.log/sys.log/events.log/http.log),或像本实验室一样直接用编排引擎的日志采集(docker logs)作为主日志通道。sys.log 是主日志(含用户进房/频道加载),error.log 是错误与堆栈,events.log 记录注册、封禁等关键事件——排障优先级 error.log > sys.log > events.log(实战用法见《CyTube 常用命令与运维实战(核心篇)》)。

8.6 配置改了不生效:conf 目录挂载缺失

现象:往 conf/ 放了扩展配置文件(如 prometheus.toml),应用完全读不到;改 config.yaml 重启,行为也没变。

定位:最初编排只挂载了 ./conf/config.yaml:/opt/cytube/config.yaml 单文件,宿主 conf/ 目录本身与应用的 /opt/cytube/conf/ 目录不连通——应用启动日志里 No camo/email/captcha configuration found 一直在提示"找不到扩展配置"。

处置:编排中补一条整目录挂载 ./conf:/opt/cytube/conf,重启后启动日志出现:

[INFO] config: Loaded prometheus configuration from conf/prometheus.toml.  Prometheus listener is ENABLED

教训:CyTube 的配置体系是"主文件 config.yaml + conf/ 目录下的扩展文件"两层结构,编排挂载必须两层都覆盖。

九、部署验收清单

最后给一张验收卡,全部打勾即部署完成:

#验收项命令/操作预期
1两个服务均为运行中docker compose ps应用 Up,数据库 Up (healthy)
2Web 端口探活curl -s -o /dev/null -w '%{http_code}' http://服务器IP:8129/200
3实时通道探活curl -s "http://服务器IP:8130/socket.io/?EIO=4&transport=polling"返回 0{"sid":...}
4数据表齐全show tables;14 张表
5管理员提权查询 users 表global_rank=255
6频道页可进访问 /r/频道名200
7直链视频入队队列添加 MP4 直链显示时长与编码元数据
8双端同步两个标签页同时观看进度逐秒一致

至此,一个可用的多人观影室已经上线。下一步建议:把 config.yaml 里与站点 identity 相关的参数(域名、标题、Cookie 密钥、注册限制)按真实需求调整——每个参数的含义、默认值与改值验证,见《CyTube 配置参数详解》;日常管理与备份,见《CyTube 常用命令与运维实战(核心篇)》。

十、参考链接