简体   繁体   English

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

[英]How to stream Docker container logs via the Go SDK

I'm writing a tool for some game server software in Go called sampctl and the primary function is to spin up a Docker container for a server instance and then capture the logs coming out of the container, clean them up a bit and send them to a location of the users choice such as Elasticsearch or an administration panel for later analysis. 我在Go中为某些游戏服务器软件编写了一个名为sampctl的工具 ,其主要功能是为服务器实例启动一个Docker容器,然后捕获从容器中出来的日志,对其进行清理,然后将其发送到用户选择的位置,例如Elasticsearch或管理面板,以供以后分析。

I've got everything else working, the only thing I can't seem to get to work is streaming logs. 我已经完成了所有其他工作,似乎无法工作的唯一一件事就是日志。 I can get logs if the application in the container crashes but I want to stream the logs in realtime. 如果容器中的应用程序崩溃,我可以获取日志,但是我想实时传输日志。

I've tried using a scanner with the ContainerLogs returned ReadCloser but that just hung at the terminal. 我试过使用带有ContainerLogs返回的ReadCloser的扫描仪,但是它只是挂在终端上。

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

Does ContainerLogs even support streaming? ContainerLogs是否甚至支持流传输? Or will I need to figure out another solution... 还是我需要找出另一个解决方案...

Apologies if this is more of a Go question than a Docker question, I wasn't too sure whether or not to post here or on GoLangBridge... 抱歉,如果这不是Go问题而不是Docker问题,我不太确定是否要在此处发布或在GoLangBridge上发布...

Have you read the docs? 你看过文档吗? The stream has metadata embedded, so you can't quite just pipe it to the console. 流中嵌入了元数据,因此您不能仅将其通过管道传输到控制台。

I have the following code in a monitoring application: 我在监视应用程序中具有以下代码:

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

It streams as long as I keep it running. 只要我保持运行它就会流。 There is also this helper package to do most of that for you, but in my case I need to handle the messages individually like this for other reasons. 还有一个帮助程序包可以为您完成大多数操作,但就我而言,由于其他原因,我需要像这样单独处理消息。

Okay, I managed to resolve this and I'm not sure why captncraig's answer didn't work which I'm still curious about but hey, here's my solution: 好的,我设法解决了这个问题,我不确定为什么captncraig的答案不起作用,我仍然对此感到好奇,但是,这是我的解决方案:

I had to set some other options in my ContainerCreate call: 我必须在ContainerCreate调用中设置其他一些选项:

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

Then the scanner.Scan() method worked perfectly! 然后, scanner.Scan()方法运行良好!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM