如何通过Go SDK流式传输Docker容器日志

Sou*_*aws 2 io logging stream go docker

我正在为Go中的一些游戏服务器软件编写一个名为sampctl的工具,主要功能是为服务器实例启动Docker容器,然后捕获容器中的日志,清理它们并发送给它们用户选择的位置,例如Elasticsearch或管理面板,供以后分析.

我已经完成了其他所有工作,我唯一无法工作的就是流式传输日志.如果容器中的应用程序崩溃但我想实时流式传输日志,我可以获取日志.

我已经尝试使用带有ContainerLogs返回的扫描仪,ReadCloser但只是挂在终端上.

https://github.com/Southclaws/sampctl/blob/9c76b4dd1b3dbb9e18927da10028d5beeb94f728/run_container.go#L64-L67

难道ContainerLogs甚至支持流?或者我需要找出另一个解决方案......

抱歉,如果这是一个Go问题而不是Docker问题,我不太确定是否要在这里发布或在GoLangBridge上发布...

Sou*_*aws 7

好吧,我设法解决了这个问题,我不确定为什么 captncraig 的答案不起作用,我仍然很好奇,但是嘿,这是我的解决方案:

我必须在ContainerCreate通话中设置一些其他选项:

        Tty:          true,
        AttachStdout: true,
        AttachStderr: true,
Run Code Online (Sandbox Code Playgroud)

然后这个scanner.Scan()方法就完美了!

这是更新后的代码:https://github.com/Southclaws/sampctl/blob/1ad7971d817031bd5a5b3acfad3bf2ea69232c98/run_container.go#L56-L70


cap*_*aig 5

你读过文档吗?流中嵌入了元数据,因此您无法将其直接传输到控制台.

我在监视应用程序中有以下代码:

    i, err := cli.ContainerLogs(context.Background(), cid, types.ContainerLogsOptions{
        ShowStderr: true,
        ShowStdout: true,
        Timestamps: false,
        Follow:     true,
        Tail:       "40",
    })
    if err != nil {
        log.Fatal(err)
    }
    hdr := make([]byte, 8)
    for {
        _, err := i.Read(hdr)
        if err != nil {
            log.Fatal(err)
        }
        var w io.Writer
        switch hdr[0] {
        case 1:
            w = os.Stdout
        default:
            w = os.Stderr
        }
        count := binary.BigEndian.Uint32(hdr[4:])
        dat := make([]byte, count)
        _, err = i.Read(dat)
        fmt.Fprint(w, string(dat))
    }
Run Code Online (Sandbox Code Playgroud)

只要我保持运行,它就会流动.还有这个帮助程序包可以为您完成大部分操作,但在我的情况下,我需要像其他原因单独处理这些消息.