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

时间:2017-09-26 14:09:09

标签: docker logging go io stream

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

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

我尝试使用ContainerLogs返回ReadCloser的扫描仪,但只是挂在终端上。

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

ContainerLogs是否支持流媒体?或者我需要找出另一种解决方案......

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

2 个答案:

答案 0 :(得分:5)

您是否阅读过the docs?该流已嵌入元数据,因此您无法将其传输到控制台。

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

    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))
    }

只要我保持运行它就会流动。还有this helper package为你做大部分工作,但在我的情况下,我需要像其他原因单独处理这些消息。

答案 1 :(得分:0)

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

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

        Tty:          true,
        AttachStdout: true,
        AttachStderr: true,

然后scanner.Scan()方法完美无缺!

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