如何在不重新加载页面的情况下使用express将docker容器日志流式传输到Webbrowser?

zi8p0yeb  于 2023-04-11  发布在  Docker
关注(0)|答案(1)|浏览(93)

什么是最好的方法来流我的docker容器日志到我的Web浏览器,而不刷新使用expressnode-docker-api
这是我目前的剧本。

app.get('/container/:id/log', async function(req, res){
    await checkTokenHeader(req, res);
    //todo: Check if Container exist
    let container = await getDockerContainer(req.params.id);

    await container.logs({
        follow: true,
        stdout: true,
        stderr: true
    }).then(async function(stream){
        res.setHeader('Content-Type', 'text/html; charset=utf-8');
        res.setHeader('Transfer-Encoding', 'chunked');
        console.log(stream)
        //stream.on('data', info => res.write(info.toString('utf-8').slice(8)))
        //stream.on('data', info => console.log(info.toString('utf-8').slice(8)))
        
        //I WANT TO STREAM THE OUTPUT TO Webbrowser or inside a div

    })
});

我尝试使用res.writeres.send,但没有任何效果

jmo0nnb3

jmo0nnb31#

实现你所描述的一种可能的方法是:
1.使用一些客户端JavaScript构建一个HTML文档以获取日志
1.建立WebSocket连接以将日志流式传输到客户端
下面是一个非常简单的实现:

// save this to "index.mjs" and run with "node ./index.mjs"

import http from "http";

import express from "express"; // npm i express
import {
  Docker
} from "node-docker-api"; // npm i node-docker-api
import {
  WebSocketServer
} from "ws"; // npm i ws

const app = express();
const docker = new Docker({
  socketPath: "/var/run/docker.sock"
});

app.get("/container/:id/log", async function(req, res) {
  res.setHeader("Content-Type", "text/html; charset=utf-8");

  // This is a naïve way of building an HTML document. 
  // You most likely want to to build this from a template
  res.end(`
    <!DOCTYPE html>
    <html>
      <head>
        <title>Container Logs</title>
      </head>
      <body>
        <h1>Container Logs</h1>
        <div id="logs"></div>
        <script>
          const ws = new WebSocket(\`ws://\${window.location.host}/${req.params.id}\`);
          ws.onmessage = (event) => {
            const log = document.createElement("p");
            log.innerText = event.data;
            document.getElementById("logs").appendChild(log);
            window.scrollTo(0, document.body.scrollHeight);
          };
        </script>
      </body>
    </html>
  `);
});

const server = http.createServer(app);
const wss = new WebSocketServer({
  server
});

wss.on("connection", async(ws, req) => {
  const containerId = req.url.split("/")[1];

  // TODO: validate containerId

  ws.on("error", console.error);

  let container = docker.container.get(containerId);
  const stream = await container.logs({
    follow: true,
    stdout: true,
    stderr: true,
  });

  ws.once("close", () => {
    stream.removeAllListeners();
    stream.destroy();
  });

  stream.on("data", (info) => ws.send(info.toString("utf-8")));
});

server.listen(3000, () => {
  console.log("Server running on port 3000");
});

使用以下docker-compose.yml运行上面的代码:

version: "3.8"
services:
  counter:
    image: busybox:latest
    init: true
    command: '/bin/sh -c "while true; do date; sleep 1; done"'

在不刷新的情况下将日志行追加到页:

相关问题