首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Docker (Moby) golang映像生成日志是base64编码的

Docker (Moby) golang映像生成日志是base64编码的
EN

Stack Overflow用户
提问于 2022-10-20 01:48:42
回答 1查看 40关注 0票数 0

我正在寻找帮助从一个码头(buildkit/moby)图像构建请求提取图像构建日志,这个请求是由一个基于Golang的客户机使用docker客户机库发送的。

我可以请求映像,构建良好,并接收json消息的日志流,然后将它们解码为Jsonmessage消息实例。但是,来自构建器的实际日志行似乎是用base64编码的每个json消息的字段

我可以很容易地解码base64,但它们似乎包含奇怪的终端控制字符和可能是错误编码的数据,这让我怀疑它们是否实际上是某种结构的base64编码。

让我困惑的是,当显示docker buildx build的构建进度时,我在docker-ce或moby代码中找不到任何在base64 64中解码“aux”有效负载的东西。

据我所知,buildx代码对aux有效负载没有任何特殊作用:buildkit.go#L325

例如,精简的构建代码如下:

代码语言:javascript
复制
        image := Image{Name:      "test"}
        contextreader, err := archive.TarWithOptions(buildConf.Build.Context, &archive.TarOptions{})
        if err != nil {
                return err
        }
        imageBuildResponse, err := b.client.ImageBuild(
                ctx,
                contextreader,
                types.ImageBuildOptions{
                      Version:     types.BuilderBuildKit,
                      Context:     contextreader,
                      Dockerfile:  dockerfile,
                })
        if err != nil {
                return err
        }
        defer imageBuildResponse.Body.Close()


        buf := bytes.NewBuffer(nil)

        imageID := ""
        writeAux := func(msg jsonmessage.JSONMessage) {
                if msg.ID == "moby.image.id" {
                        var result types.BuildResult
                        if err := json.Unmarshal(*msg.Aux, &result); err != nil {
                            panic("don't do this in your real code")
                        }
                        imageID = result.ID
                        return
                }
                return err
        }

        err := jsonmessage.DisplayJSONMessagesStream(imageBuildResponse.Body, buf, os.Stderr.Fd(), false /* not terminal */, writeAux)
        if err != nil {
                if jerr, ok := err.(*jsonmessage.JSONError); ok {
                        // If no error code is set, default to 1
                        if jerr.Code == 0 {
                                jerr.Code = 1
                        }
                        return fmt.Errorf("error while building image: %s", jerr.Message)
                }
        }

将向stderr写入json有效负载,如

代码语言:javascript
复制
{"id":"moby.buildkit.trace","aux":"Cn0KR3NoYTI1NjozZThhMzMxYmRkZGFjNWZkYmNjOGVhMDFmYWFhYmM3MjA0MDkwMmYwNjdmYzRhOGY0NDJmMmIzYWVlN2RkNGIyGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAiYw8KaBhCykpCqAg=="}
{"id":"moby.buildkit.trace","aux":"CokBCkdzaGEyNTY6M2U4YTMzMWJkZGRhYzVmZGJjYzhlYTAxZmFhYWJjNzIwNDA5MDJmMDY3ZmM0YThmNDQyZjJiM2FlZTdkZDRiMhokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwImMPCmgYQspKQqgIyCgiZw8KaBhD08F0="}

这里的base64字符串不能作为有效的utf-8进行解码,它们也不像ISO-8859-1那样有意义。例如,使用utf-8控制台编码:

代码语言:javascript
复制
$ base64 -d <<<'Cn0KR3NoYTI1NjozZThhMzMxYmRkZGFjNWZkYmNjOGVhMDFmYWFhYmM3MjA0MDkwMmYwNjdmYzRhOGY0NDJmMmIzYWVlN2RkNGIyGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAiYw8KaBhCykpCqAg=='

}
Gsha256:3e8a331bdddac5fdbcc8ea01faaabc72040902f067fc4a8f442f2b3aee7dd4b2�$[internal] load remote build context*
                                                                                                              ������

它看起来可能是一个结构,但对于我的生活,我找不到什么破译和处理它。

EN

回答 1

Stack Overflow用户

发布于 2022-10-20 04:48:33

所以我当然会在写这个问题时找到答案.

writeAux函数在build_buildkit.go中调用实例,这是真正的工作。我一定是瞎了。

这些消息是来自StatusResponse包的github.com/moby/buildkit/api/services/control的序列化实例。它们被从byte 64解码的字节序列中解组并被检查。如果您想要日志并跳过所有其他内容,只需查找具有非空Logs成员数组的实例,例如在上面的writeAux函数中如下所示:

代码语言:javascript
复制
                } else if msg.ID == "moby.buildkit.trace" {
                        // Process the message like
                        // https://github.com/docker/docker-ce/blob/523cf7e71252013fbb6a590be67a54b4a88c1dae/components/cli/cli/command/image/build_buildkit.go#L386
                        // the 'tracer.write' method in build_buildkit.go
                        var resp controlapi.StatusResponse
                        var dt []byte
                        // ignoring all messages that are not understood
                        if err := json.Unmarshal(*msg.Aux, &dt); err != nil {
                                return
                        }
                        if err := (&resp).Unmarshal(dt); err != nil {
                                return
                        }
                        for _, v := range resp.Vertexes {
                                fmt.Printf("layer: %+v", v)
                        }
                        for _, v := range resp.Statuses {
                                fmt.Printf("status: %+v", v)
                        }
                        for _, v := range resp.Logs {
                                fmt.Printf("log: msg.Msg)
                        }
                  }

json.Unmarshalcontrolapi.StatusResponse.Unmarshal为您做base64解码和解压缩。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74133617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档