我正在寻找帮助从一个码头(buildkit/moby)图像构建请求提取图像构建日志,这个请求是由一个基于Golang的客户机使用docker客户机库发送的。
我可以请求映像,构建良好,并接收json消息的日志流,然后将它们解码为Jsonmessage消息实例。但是,来自构建器的实际日志行似乎是用base64编码的每个json消息的字段。
我可以很容易地解码base64,但它们似乎包含奇怪的终端控制字符和可能是错误编码的数据,这让我怀疑它们是否实际上是某种结构的base64编码。
让我困惑的是,当显示docker buildx build的构建进度时,我在docker-ce或moby代码中找不到任何在base64 64中解码“aux”有效负载的东西。
据我所知,buildx代码对aux有效负载没有任何特殊作用:buildkit.go#L325
例如,精简的构建代码如下:
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有效负载,如
{"id":"moby.buildkit.trace","aux":"Cn0KR3NoYTI1NjozZThhMzMxYmRkZGFjNWZkYmNjOGVhMDFmYWFhYmM3MjA0MDkwMmYwNjdmYzRhOGY0NDJmMmIzYWVlN2RkNGIyGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAiYw8KaBhCykpCqAg=="}
{"id":"moby.buildkit.trace","aux":"CokBCkdzaGEyNTY6M2U4YTMzMWJkZGRhYzVmZGJjYzhlYTAxZmFhYWJjNzIwNDA5MDJmMDY3ZmM0YThmNDQyZjJiM2FlZTdkZDRiMhokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwImMPCmgYQspKQqgIyCgiZw8KaBhD08F0="}这里的base64字符串不能作为有效的utf-8进行解码,它们也不像ISO-8859-1那样有意义。例如,使用utf-8控制台编码:
$ base64 -d <<<'Cn0KR3NoYTI1NjozZThhMzMxYmRkZGFjNWZkYmNjOGVhMDFmYWFhYmM3MjA0MDkwMmYwNjdmYzRhOGY0NDJmMmIzYWVlN2RkNGIyGiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAiYw8KaBhCykpCqAg=='
}
Gsha256:3e8a331bdddac5fdbcc8ea01faaabc72040902f067fc4a8f442f2b3aee7dd4b2�$[internal] load remote build context*
������它看起来可能是一个结构,但对于我的生活,我找不到什么破译和处理它。
发布于 2022-10-20 04:48:33
所以我当然会在写这个问题时找到答案.
writeAux函数在build_buildkit.go中调用实例,这是真正的工作。我一定是瞎了。
这些消息是来自StatusResponse包的github.com/moby/buildkit/api/services/control的序列化实例。它们被从byte 64解码的字节序列中解组并被检查。如果您想要日志并跳过所有其他内容,只需查找具有非空Logs成员数组的实例,例如在上面的writeAux函数中如下所示:
} 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.Unmarshal和controlapi.StatusResponse.Unmarshal为您做base64解码和解压缩。
https://stackoverflow.com/questions/74133617
复制相似问题