本文是一份脱敏后的部署记录。为避免把可直接用于连接或登录的信息公开,文中不包含服务密码、服务器码、连接 ID、公网 IP、Docker Hub Token、SSH 私钥或完整运行日志。
一、目标
在一台腾讯云 Ubuntu 服务器上,用 Docker Compose 统一管理三类远程服务:
- NVDA Remote:为 NVDA 屏幕阅读器提供远程协助;
- RustDesk:提供开源远程桌面服务;
- 争渡远程:使用争渡官方提供的 Linux x64 服务端。
统一使用子域名 r.example.com 的思路,实际部署时按自己的域名替换。网站说明页单独由 Caddy 提供 HTTPS,方便用户查看地址、端口和客户端设置方法。
二、目录与账号
服务数据集中放在:
| |
其中按服务分目录:
| |
服务器上创建了专用的 remote 用户组和受限系统用户。服务容器不需要把该用户加入 sudo 或 Docker 组;Docker Compose 由已有的运维账号执行,服务数据目录则使用独立权限保存。
三、Compose 统一管理
NVDA Remote、RustDesk 的 hbbs/hbbr 和争渡远程都放在同一个 Compose 项目中。这样可以统一完成:
- 启动、停止和查看状态;
- 数据目录挂载;
- 容器自动重启;
- 端口映射;
- 版本更新。
争渡官方服务端要求同一个端口同时提供 TCP 和 UDP,因此 Compose 中需要同时发布:
| |
实际运行争渡服务时还使用了官方安装脚本采用的目录参数:
| |
这一步很重要。只运行二进制而不传入数据目录时,服务端不能正确完成 ID 数据初始化。
四、最初遇到的问题
1. 云安全组没有放行
服务器本机监听和 UFW 放行,并不代表公网一定可用。腾讯云安全组还需要放行对应入站端口。
2. Docker 桥接网络对 UDP 注册不理想
争渡远程客户端可以发出 UDP 请求,但在 Docker bridge 模式下,服务端注册流程表现不稳定。后来将争渡容器改为:
| |
使官方服务端直接使用宿主机网络,客户端注册过程更加符合官方安装方式。
3. SQLite 原生库名称与权限
争渡 Linux 服务端依赖随包提供的 SQLite.Interop.dll。容器中先后遇到了:
- 基础镜像缺少运行时依赖;
- 原生库搜索路径不包含
/app; - 文件权限导致非 root 用户无法读取;
- 官方程序寻找的库名称与压缩包文件名不完全一致。
最终在镜像中完成了:
- 设置
LD_LIBRARY_PATH=/app; - 修正二进制与 SQLite 原生库权限;
- 为兼容名称建立符号链接;
- 以非 root 用户运行服务。
修复后,持久化目录出现了有效的 data.db,客户端可以正常获取 ID 并建立远程连接。
五、排查方法
遇到客户端拿不到 ID 时,按下面顺序排查比盲目重装更有效:
- 查看 Compose 状态:
1docker compose ps - 查看本机 TCP/UDP 监听:
1ss -lntup | grep 23188 - 检查云安全组和 UFW;
- 从公网测试 TCP 端口;
- 用临时
tcpdump确认客户端 UDP 请求是否到达; - 查看争渡服务端
log.txt; - 确认客户端与服务端版本、密码和服务器设置一致;
- 清理旧连接状态后重新生成 ID。
抓包时只查看协议元数据即可,不要公开完整数据包,因为其中可能包含客户端哈希、连接信息或其他敏感内容。
六、网页说明与无障碍
远程服务说明页使用原生 HTML 控件,重点做了几项简化:
- 每项信息都有单独的复制按钮;
- 每个服务都有“复制此服务信息”;
- 按钮可通过 Tab 聚焦;
- Enter 或空格才执行复制;
- 复制结果使用
role="status"和aria-live提示屏幕阅读器; - 网页不公开服务密码、服务器码或连接 ID,敏感信息改为通过可信渠道提供;
- 页面会定期检查内容是否更新,检测到新版本后再刷新,避免无意义地频繁刷新。
七、自动更新的取舍
Watchtower 与当前 Docker API 版本存在兼容性问题,因此改用 systemd timer 每天执行 Compose 更新。更新脚本只拉取公开的 NVDA Remote 与 RustDesk 镜像;争渡镜像由自己的构建流程发布后,再按版本明确更新,避免自动任务误拉取不存在的本地标签。
八、镜像构建与分发
争渡镜像使用官方 Linux x64 服务端文件构建,并在 GitHub Actions 中通过 Docker Hub Access Token 发布。仓库保持私有,Actions Secrets 只保存:
| |
不要把密码、Token 或私钥写入仓库、网页、日志或文章。Docker Hub 的镜像说明与 GitHub README 可以分别维护;镜像版本通过 Git tag 触发发布。
九、最后的连接信息
实际服务器地址、端口和密码请以自己的受保护配置为准。不要从博客文章复制密码,也不要把密码与服务器码放在同一篇公开文章中。
镜像项目仓库:
https://github.com/dpy013/zdsr-remote-image
Docker Hub 镜像搜索地址:
https://hub.docker.com/search?q=zdsr-remote&type=image
如果要直接使用 Docker Hub 仓库,请在 Docker Hub 中搜索
zdsr-remote,并核对发布者、版本标签和 README 后再拉取。