KDOC 25: docker progress を読む

Dockerでimage pullをするときに出る、プログレスバーをどうやっているのか調べる。

Tasks

DONE Progressのコードを読む

を見て、progressという箇所があることを知る。ここを読んでみる。

  • インターフェースprogressUpdaterは更新するインターフェース
    • 構造体pullProgressはインターフェースを満たす。こいつはStore, ShowExistsを持っていて情報を保持してる
  • 構造体jobsはミューテックスとdescを持つ。descsは何に使われている
    • イメージの情報が入ってるんだろうな
type Descriptor struct {
	// MediaType is the media type of the object this schema refers to.
	MediaType string `json:"mediaType,omitempty"`

	// Digest is the digest of the targeted content.
	Digest digest.Digest `json:"digest"`

	// Size specifies the size in bytes of the blob.
	Size int64 `json:"size"`

	// URLs specifies a list of URLs from which this object MAY be downloaded
	URLs []string `json:"urls,omitempty"`

	// Annotations contains arbitrary metadata relating to the targeted content.
	Annotations map[string]string `json:"annotations,omitempty"`

	// Data is an embedding of the targeted content. This is encoded as a base64
	// string when marshalled to JSON (automatically, by encoding/json). If
	// present, Data can be used directly to avoid fetching the targeted content.
	Data []byte `json:"data,omitempty"`

	// Platform describes the platform which the image in the manifest runs on.
	//
	// This should only be used when referring to a manifest.
	Platform *Platform `json:"platform,omitempty"`

	// ArtifactType is the IANA media type of this artifact.
	ArtifactType string `json:"artifactType,omitempty"`
}
  • 表示するのはshowProgress。こいつはupdater interfaceを受け取って、更新する方法を抽象化している
    • データはレシーバのjobsに保持している

20230527-progress.drawio.svg

  • UpdateProgressは何をしているか
    • storeの中のstatusを更新する(アクティブなものだけにする)
    • 引数のjobsでループ
    • アクティブなjobのときだけWriteProgress()で進捗を書き込む
    • 条件によって、「ダウンロード完了」とか、「すでに存在」とかメッセージを分ける

DONE Pullのコードを読む

  • daemon/containerd/image_pull.go
  • レシーバはImageService。イメージに関するアクションを一手に引き受けるインターフェース及び構造体
  • platformを読み取ってオプションに追加する
  • image名をパースしてrefオブジェクトを作成する
  • tagOrDigestをパースして分離する
  • パースした結果はrefに入れる
  • リゾルバーを作成してオプションに追加する
  • ハンドル関数をオプションに追加する
    • ハンドル関数の中身でjobsを追加している
  • ここのハンドラは何をするのだろう
  • JSONProgressOutputオブジェクトを作成
  • finishProgressを作成
  • deferでfinishProgress()を実行する
  • オプションにWithPullUnpack, WithPullSnapshotterを追加する
    • 展開とかスナップショット…
  • Pullを実行する。これが本質か。Pull自体はrefがあれば実行できる。コードの途中は本質ではない。
    • imageService.client.Pull なので、普通にdocker clientのpullを実行するんだろう