You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:34:52