【问题标题】:How to stream Docker container logs via the Go SDK如何通过 Go SDK 流式传输 Docker 容器日志
【发布时间】:2018-03-07 19:28:05
【问题描述】:

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

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

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

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

ContainerLogs 是否支持流式传输?还是我需要想出另一个解决方案...

抱歉,如果这更像是一个 Go 问题而不是 Docker 问题,我不太确定是在此处发布还是在 GoLangBridge 上发布...

【问题讨论】:

    标签: docker logging go io stream


    【解决方案1】:

    您是否阅读过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 可以为您完成大部分工作,但就我而言,出于其他原因,我需要像这样单独处理消息。

    【讨论】:

    • 哦,我漫无目的地剥离元数据,并认为我可以一直阅读到 \n...我会试一试,谢谢!
    • 不幸的是,它只是挂在i.Read(hdr) - 创建容器时我必须在container.Config 中放入任何设置吗?
    • 旁注:如果我在另一个终端中docker attachCTRL+C,它会突然输出所有内容......它似乎在等待输出时刚刚锁定,但是一旦内部应用程序结束,它冲洗!
    • 好吧,文档没有说明元数据...在这里,我找到了解释:ahmet.im/blog/docker-logs-api-binary-format-explained
    • @FrancescoPasa 谢谢,看来过去 3 年 go 文档变得不那么明确了。
    【解决方案2】:

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

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

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

    然后scanner.Scan() 方法完美运行!

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

    【讨论】:

    • 对我有用的是在容器日志功能中有Follow 选项
    猜你喜欢
    • 1970-01-01
    • 2019-02-09
    • 2018-03-13
    • 2018-09-07
    • 2016-10-11
    • 2021-03-16
    • 1970-01-01
    • 2021-10-20
    • 2021-08-13
    相关资源
    最近更新 更多