Golang – Docker API – 分析ImagePull的结果

我正在开发一个使用Docker APIGo脚本,用于我的项目。 我login到我的资源库后,我拉我想要的Docker图像,但问题是ImagePull函数返回io.ReadCloser的实例,我只能通过传递给系统输出:

 io.Copy(os.Stdout, pullResp) 

很酷,我可以看到答复,但我找不到一个体面的方式来parsing它,并实现一个逻辑取决于它,这将做一些事情,如果一个新版本的图像已被下载,其他事情,如果图像是最新的。
如果您曾经遇到过这个问题,我会很乐意分享您的经验。

@ radoslav-stoyanov在使用我的例子之前呢

# docker rmi busybox

然后运行代码

 package main import ( "encoding/json" "fmt" "github.com/docker/distribution/context" docker "github.com/docker/engine-api/client" "github.com/docker/engine-api/types" "io" "strings" ) func main() { // DOCKER cli, err := docker.NewClient("unix:///var/run/docker.sock", "v1.28", nil, map[string]string{"User-Agent": "engine-api-cli-1.0"}) if err != nil { panic(err) } imageName := "busybox:latest" events, err := cli.ImagePull(context.Background(), imageName, types.ImagePullOptions{}) if err != nil { panic(err) } d := json.NewDecoder(events) type Event struct { Status string `json:"status"` Error string `json:"error"` Progress string `json:"progress"` ProgressDetail struct { Current int `json:"current"` Total int `json:"total"` } `json:"progressDetail"` } var event *Event for { if err := d.Decode(&event); err != nil { if err == io.EOF { break } panic(err) } fmt.Printf("EVENT: %+v\n", event) } // Latest event for new image // EVENT: {Status:Status: Downloaded newer image for busybox:latest Error: Progress:[==================================================>] 699.2kB/699.2kB ProgressDetail:{Current:699243 Total:699243}} // Latest event for up-to-date image // EVENT: {Status:Status: Image is up to date for busybox:latest Error: Progress: ProgressDetail:{Current:0 Total:0}} if event != nil { if strings.Contains(event.Status, fmt.Sprintf("Downloaded newer image for %s", imageName)) { // new fmt.Println("new") } if strings.Contains(event.Status, fmt.Sprintf("Image is up to date for %s", imageName)) { // up-to-date fmt.Println("up-to-date") } } } 

你可以看到API格式来创build你的结构(如我的Event )在这里阅读它们https://docs.docker.com/engine/api/v1.27/#operation/ImageCreate

我希望它可以帮助你解决你的问题,谢谢。

我使用了类似的方法来达到我的目的(不是一个移动客户端)。 通常情况下,阅读stream响应的想法是相同的 试试看,并实施你的。

读取任何响应types的stream响应:

 reader := bufio.NewReader(pullResp) defer pullResp.Close() // pullResp is io.ReadCloser var resp bytes.Buffer for { line, err := reader.ReadBytes('\n') if err != nil { // it could be EOF or read error // handle it break } resp.Write(line) resp.WriteByte('\n') } // print it fmt.Println(resp.String()) 

但是,您的评论中的示例响应似乎有效的JSON结构。 json.Decoder是读取JSONstream的最佳方法。 这只是一个想法,

 type ImagePullResponse struct { ID string `json"id"` Status string `json:"status"` ProgressDetail struct { Current int64 `json:"current"` Total int64 `json:"total"` } `json:"progressDetail"` Progress string `json:"progress"` } 

而且呢

 d := json.NewDecoder(pullResp) for { var pullResult ImagePullResponse if err := d.Decode(&pullResult); err != nil { // handle the error break } fmt.Println(pullResult) }