求助:使用xterm.js attach插件连接Docker容器终端(新版Docker)
实现xterm.js + Docker容器终端连接(新版Docker验证可行)
我上个月刚在Docker 24.0.6版本上成功搞定了这个功能,踩了几个小坑,分享下我的实操步骤,应该能帮你解决问题。
第一步:确保Docker API支持WebSocket连接
首先得让Docker daemon允许外部通过TCP访问,WebSocket依赖这个:
- 编辑Docker daemon配置文件(比如
/etc/docker/daemon.json),添加以下内容:{ "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"] } - 重启Docker服务生效:
sudo systemctl restart docker
注意:本地测试这么弄没问题,生产环境一定要加TLS认证,别直接裸开2375端口!
第二步:xterm.js + attach插件的核心代码
我用的是xterm.js 5.3.0和xterm-addon-attach 0.10.0,核心逻辑分两步:先创建exec实例,再通过WebSocket绑定终端,代码如下:
import { Terminal } from 'xterm'; import { AttachAddon } from 'xterm-addon-attach'; import 'xterm/css/xterm.css'; // 初始化终端实例 const term = new Terminal({ cursorBlink: true, fontSize: 14, theme: { background: '#1e1e1e' } }); term.open(document.getElementById('terminal-container')); // 替换成你的容器ID const containerId = 'your-container-id-here'; // 第一步:创建exec会话 fetch(`http://localhost:2375/containers/${containerId}/exec`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ AttachStdin: true, AttachStdout: true, AttachStderr: true, Tty: true, Cmd: ['/bin/bash'] // 容器里要存在的shell命令 }) }) .then(res => res.json()) .then(execData => { const execId = execData.Id; // 第二步:建立WebSocket连接并绑定终端 const socket = new WebSocket( `ws://localhost:2375/containers/${containerId}/exec/${execId}/attach/ws?stdin=1&stdout=1&stderr=1&tty=1` ); const attachAddon = new AttachAddon(socket); term.loadAddon(attachAddon); // 处理终端窗口大小调整 term.onResize(size => { fetch(`http://localhost:2375/exec/${execId}/resize`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ h: size.rows, w: size.cols }) }); }); });
关于Docker API变更的问题
你提到的GitHub Issue里的API变动,我也遇到了——主要是Docker 20.10+版本后,对exec attach的WebSocket参数做了强制要求:
- 必须在WebSocket URL里显式传
stdin=1&stdout=1&stderr=1&tty=1这些参数,之前版本可能可以省略 - 创建exec实例时必须设置
Tty: true,否则终端会出现输入无响应的情况
几个容易踩的坑
- 跨域问题:如果你的Web应用和Docker API不在同域,要么给Docker daemon配置CORS,要么用Nginx做反向代理转发请求
- 容器状态:必须确保容器处于运行状态,且里面安装了指定的shell(比如bash)
- 防火墙拦截:本地测试时注意关闭防火墙,或者开放2375端口的访问权限
我当时卡了快半天,最后发现是WebSocket URL漏传了参数,加上Docker daemon没开TCP端口,调整后立马就正常了,新版Docker完全可以实现这个功能,放心搞!
内容的提问来源于stack exchange,提问作者the_el_jefe
相关产品推荐
相关产品推荐

