如何在使用Go代码拉取containerd镜像时显示拉取进度
实现containerd镜像拉取进度显示的思路
完全可以实现拉取进度展示,核心是利用containerd提供的拉取选项钩子,监听镜像层的下载进度事件。
具体实现步骤
- 自定义进度追踪器,实现
content.ProgressTracker接口,该接口需要处理Progress事件,包含已下载字节数、总字节数等核心信息。 - 调用
client.Pull时,通过containerd.WithPullProgress选项传入自定义的进度追踪逻辑。 - 在进度处理函数中,实时计算并打印控制台进度信息(比如
BytesPulled/BytesTotal或百分比)。
改造后的示例代码
package main import ( "context" "fmt" "log" "sync" "github.com/containerd/containerd" "github.com/containerd/containerd/content" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/platforms" ) // 自定义进度追踪器,处理多goroutine并发更新的线程安全问题 type progressTracker struct { mu sync.Mutex stats map[string]content.Progress total int64 pulled int64 } func newProgressTracker() *progressTracker { return &progressTracker{ stats: make(map[string]content.Progress), } } // Track 实现content.ProgressTracker接口的核心方法,接收每个镜像层的进度事件 func (pt *progressTracker) Track(ctx context.Context, progress content.Progress) { pt.mu.Lock() defer pt.mu.Unlock() pt.stats[progress.Digest.String()] = progress // 重新统计全局总字节数和已下载字节数 pt.total = 0 pt.pulled = 0 for _, p := range pt.stats { pt.total += p.Total pt.pulled += p.Offset } // 实时打印进度,\r实现控制台单行刷新 fmt.Printf("\r拉取进度: %d/%d bytes (%.2f%%)", pt.pulled, pt.total, float64(pt.pulled)/float64(pt.total)*100) } func main() { // 建立containerd连接 client, err := containerd.New("/run/containerd/containerd.sock") if err != nil { log.Fatal(err) } defer client.Close() // 指定k8s.io命名空间 ctx := namespaces.WithNamespace(context.Background(), "k8s.io") // 初始化进度追踪器 tracker := newProgressTracker() // 拉取镜像,传入进度追踪选项 image, err := client.Pull( ctx, "docker.io/library/openjdk:17", containerd.WithPullUnpack, containerd.WithPullProgress(tracker.Track), // 关键:绑定进度追踪逻辑 containerd.WithPlatform(platforms.Default()), ) if err != nil { log.Fatal(err) } fmt.Printf("\n拉取完成:%s\n", image.Name()) }
关键细节说明
content.ProgressTracker是containerd官方提供的标准进度追踪接口,仅需实现Track方法即可接收所有镜像层的下载进度事件。- 使用
sync.Mutex是因为Track方法会被多个goroutine并发调用,需要保证统计数据的线程安全。 - 可以根据需求自定义进度展示格式,比如替换为带进度条的输出,或者设置进度更新阈值减少控制台刷新频率。
内容的提问来源于stack exchange,提问作者haojie zhang
相关产品推荐
相关产品推荐

