Golang - Docker API - 解析 ImagePull 的结果
Golang - Docker API - parse result of ImagePull
我正在开发一个 Go
脚本,该脚本使用 Docker API
用于我的项目。登录到我的存储库后,我拉取了我想要的 Docker 图像,但问题是 ImagePull function returns an instance of io.ReadCloser,我只能通过以下方式传递给系统输出:
io.Copy(os.Stdout, pullResp)
很高兴我能看到响应,但我找不到合适的方法来解析它并根据它实现逻辑,如果下载了新版本的图像,它会做一些事情,和其他东西,如果图像是最新的。
如果您遇到过这个问题,如果您分享您的经验,我将很高兴。
@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 格式来创建您的结构(比如我的 Event
),以便在此处阅读它们 https://docs.docker.com/engine/api/v1.27/#operation/ImageCreate
希望能帮到您解决问题,谢谢
我已经为我的目的使用了类似的方法(不是 moby 客户端)。通常想法与读取流响应相同。试一试并实现你的。
正在读取任何响应类型的流响应:
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 是读取 JSON 流的最佳方式。这只是一个想法-
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)
}
你可以导入github.com/docker/docker/pkg/jsonmessage
and use both JSONMessage and JSONProgress解码流但是更容易调用
DisplayJSONMessagesToStream:它既解析流又将消息显示为文本。以下是使用 stderr 显示消息的方法:
reader, err := cli.ImagePull(ctx, myImageRef, types.ImagePullOptions{})
if err != nil {
return err
}
defer reader.Close()
termFd, isTerm := term.GetFdInfo(os.Stderr)
jsonmessage.DisplayJSONMessagesStream(reader, os.Stderr, termFd, isTerm, nil)
好的是它适应输出:如果这是一个 TTY(docker pull
的方式),它会更新行,但如果输出被重定向到一个文件,它不会。
我正在开发一个 Go
脚本,该脚本使用 Docker API
用于我的项目。登录到我的存储库后,我拉取了我想要的 Docker 图像,但问题是 ImagePull function returns an instance of io.ReadCloser,我只能通过以下方式传递给系统输出:
io.Copy(os.Stdout, pullResp)
很高兴我能看到响应,但我找不到合适的方法来解析它并根据它实现逻辑,如果下载了新版本的图像,它会做一些事情,和其他东西,如果图像是最新的。
如果您遇到过这个问题,如果您分享您的经验,我将很高兴。
@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 格式来创建您的结构(比如我的 Event
),以便在此处阅读它们 https://docs.docker.com/engine/api/v1.27/#operation/ImageCreate
希望能帮到您解决问题,谢谢
我已经为我的目的使用了类似的方法(不是 moby 客户端)。通常想法与读取流响应相同。试一试并实现你的。
正在读取任何响应类型的流响应:
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 是读取 JSON 流的最佳方式。这只是一个想法-
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)
}
你可以导入github.com/docker/docker/pkg/jsonmessage
and use both JSONMessage and JSONProgress解码流但是更容易调用
DisplayJSONMessagesToStream:它既解析流又将消息显示为文本。以下是使用 stderr 显示消息的方法:
reader, err := cli.ImagePull(ctx, myImageRef, types.ImagePullOptions{})
if err != nil {
return err
}
defer reader.Close()
termFd, isTerm := term.GetFdInfo(os.Stderr)
jsonmessage.DisplayJSONMessagesStream(reader, os.Stderr, termFd, isTerm, nil)
好的是它适应输出:如果这是一个 TTY(docker pull
的方式),它会更新行,但如果输出被重定向到一个文件,它不会。