使用 WebTTY 在浏览器中登录边缘容器
解读
面试官想确认三件事:
- 你是否真的在弱网、低算力、无 SSH 客户端的边缘场景里交付过容器;
- 能否把“浏览器 ⇄ WebTTY ⇄ 容器 Shell”这条链路与 Docker 安全、网络、镜像规范打通;
- 遇到端口冲突、Token 泄露、TTY 断连、容器重启后会话丢失等中国特色现场问题,有没有成体系的定位与加固套路。
回答时要体现“边缘场景优先、安全合规兜底、可运维可回滚”的落地思维,而不是简单抛命令。
知识点
- 边缘容器三大约束:CPU<1 核、内存<512 MiB、带宽<2 Mbps,镜像必须多阶段裁剪到 50 MiB 以内。
- WebTTY 主流实现:ttyd、gotty、wetty,均通过 WebSocket 暴露 /p/:id 路径;国内公网需额外过阿里云/腾讯云七层 CLB,必须支持 WSS。
- Docker 安全基线:镜像内预装 tini 或 dumb-init,ENTRYPOINT 以非 root UID≥1000启动;通过 --cap-drop ALL --security-opt no-new-privileges 关闭提权。
- 一次性 Token 机制:ttyd 的 -c 参数一次生效,边缘场景用边缘节点本地 Redis 5 秒 TTL 缓存 Token,防止浏览器缓存泄露。
- 断连自愈:容器内安装 reptyr 或 tmux,WebTTY 仅作为 WebSocket→PTY 的转发层,会话由 tmux 保持,容器重启后通过preStop hook 自动 detach。
- 国内合规:若容器运行在省级工业互联网平台,必须满足 GB/T 22239-2019 三级要求,WebTTY 流量需走国密 TLS 双证书,镜像仓库开启镜像签名与 cosign 验签。
答案
现场我会分五步落地:
- 镜像侧:Dockerfile 采用多阶段构建, alpine:3.18 基础镜像仅保留 bash、curl、tmux、tini,最终镜像 38 MiB;创建用户 webtty(uid=1001),ENTRYPOINT ["tini","--","su","-","webtty"]。
- 启动参数:
docker run -d --name edge-app
--cap-drop ALL --security-opt no-new-privileges
-p 127.0.0.1:7681:7681
-v /etc/localtime:/etc/localtime:ro
--restart unless-stopped
myreg.cn/edge/app:1.4.0
ttyd -p 7681 -c webtty:$(uuidgen) tmux new -A -s debug
解释:端口仅监听本地环回,通过边缘节点 Nginx Stream 转发实现 WSS;Token 每次容器重启自动刷新,防止历史链接重放。 - 浏览器访问:
边缘节点已预置国密双证书,Nginx 配置 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 路径 /terminal/ 反向代理到 127.0.0.1:7681。
用户打开 https://edge-node-id.region.iot.company.cn/terminal/,输入**一次性 Token** 后即可获得 tmux 会话;F12 看不到 Token,因通过 HttpOnly Cookie 下发。 - 故障排查:
- 若页面空白,优先在边缘节点tcpdump -i any port 7681 确认 WebSocket 握手是否 403,一般是 Token 过期,查看 docker logs 中 uuidgen 与浏览器 Cookie 是否一致;
- 若中文乱码,exec 进容器 export LANG=C.UTF-8,并在 ttyd 启动参数加 -t fontSize=14,fontFamily=Monaco,locale=zh_CN.UTF-8;
- 容器重启后会话丢失,通过preStop hook 脚本 tmux detach-client -a 保证 tmux 仍在后台,重启后 ttyd 自动 attach 原会话。
- 安全加固:
每周通过镜像扫描工具 trivy 检查 ttyd 二进制 CVE;
使用OPA Gatekeeper 策略强制容器必须加 --cap-drop ALL,否则拒绝调度到边缘节点;
浏览器侧开启Content-Security-Policy: default-src 'self' wss:,阻断 XSS 注入。
拓展思考
如果边缘节点位于5G 专网且无外网 IP,可以把 WebTTY 与KubeEdge EdgeMesh 结合:
- EdgeMesh 在节点间建立P2P 隧道,浏览器只需访问云端统一入口 cloudcore:10003,由 EdgeMesh 把流量透传到节点 Pod 7681 端口,实现零公网暴露;
- 此时 Token 由 cloudcore 的MetaServer 统一签发,JWT 里携带节点名、Pod IP、过期时间,边缘侧轻量级 OPA 代理验签后再启动 ttyd,防止横向移动;
- 最后把整个过程固化成Helm Chart,一键安装到任意边缘 K8s 集群,实现“浏览器即运维入口”的标准化交付。