You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Express和node-docker-api无刷新在浏览器流式传输Docker容器日志?

使用Express + node-docker-api 流式传输Docker容器日志到浏览器的方案

后端调整(Express)

你的原代码已经接近正确,核心是正确处理Docker日志流并通过Express的响应流式输出,同时设置合适的响应头确保浏览器保持连接。以下是修正后的代码:

app.get('/container/:id/log', async function(req, res) {
    await checkTokenHeader(req, res);
    const container = await getDockerContainer(req.params.id);

    // 设置流式响应头,使用SSE格式更适合前端实时接收
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');
    res.flushHeaders(); // 立即发送响应头,避免浏览器等待

    // 获取容器日志流,follow设为true保持实时更新
    const stream = await container.logs({
        follow: true,
        stdout: true,
        stderr: true,
        tail: 10 // 可选:先返回最后10条历史日志,提升体验
    });

    // 处理日志流数据
    stream.on('data', (chunk) => {
        // Docker日志帧前8字节是元数据,截取实际日志内容
        const logContent = chunk.toString('utf-8').slice(8);
        // 按SSE格式输出,确保前端能正确解析
        res.write(`data: ${logContent.replace(/\n/g, '\ndata: ')}\n\n`);
    });

    // 处理流结束
    stream.on('end', () => {
        res.end();
    });

    // 处理流错误
    stream.on('error', (err) => {
        console.error('日志流异常:', err);
        res.status(500).end('日志流连接失败');
    });

    // 监听客户端断开连接,销毁流释放资源
    req.on('close', () => {
        stream.destroy();
        res.end();
    });
});

前端实现(实时显示到Div)

使用Server-Sent Events(SSE)是最简单的无刷新实时接收方案,前端代码如下:

<!-- 用于显示日志的容器 -->
<div id="log-container" style="height: 400px; overflow-y: auto; padding: 10px; background-color: #f5f5f5; font-family: monospace;"></div>

<script>
const logContainer = document.getElementById('log-container');
const targetContainerId = '你的目标容器ID'; // 可从URL参数或页面逻辑获取

// 建立SSE连接
const eventSource = new EventSource(`/container/${targetContainerId}/log`);

// 接收新日志
eventSource.onmessage = function(event) {
    const logLine = document.createElement('div');
    logLine.textContent = event.data;
    // 可选:区分stdout和stderr,比如给错误日志加红色样式
    // if (event.data.includes('ERROR')) logLine.style.color = 'red';
    logContainer.appendChild(logLine);
    // 自动滚动到最新日志
    logContainer.scrollTop = logContainer.scrollHeight;
};

// 处理连接错误
eventSource.onerror = function(error) {
    console.error('日志连接异常:', error);
    eventSource.close();
};
</script>

关键注意点

  • 响应头设置:必须启用Transfer-Encoding: chunked(Express在使用res.write时会自动添加),使用SSE格式时需指定Content-Type: text/event-stream,确保浏览器保持长连接。
  • Docker日志处理:Docker返回的日志流每帧前8字节是元数据(包含流类型、长度等),因此需要slice(8)获取实际日志内容。
  • 资源清理:监听客户端close事件,及时销毁Docker日志流,避免后端资源泄漏。
  • 体验优化:可通过tail参数返回部分历史日志,让用户打开页面时能看到之前的内容。

内容的提问来源于stack exchange,提问作者DGINX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 18:32:19