1. 程式人生 > 其它 >go-containerregistry 實戰篇之容器映象下載

go-containerregistry 實戰篇之容器映象下載

go-containerregistry 實戰篇之容器映象下載

一、庫介紹

go-containerregistry 是 google 公司開源的用於處理容器映象的golang客戶端庫,它提供了一個對映象的操作介面,這個介面背後的資源可以是 映象倉庫的遠端資源,映象的tar包,甚至是 docker daemon 程序。

它主要基於同名的python專案

下面我們就簡單介紹下如何使用這個專案來完成我們的目標—— 在程式碼中解析映象。

庫提供了crane和遠端遠端映象進行互動。

二、crane初體驗

2、1 crane 安裝和使用

Crane 是一個與遠端映象和倉庫互動的工具。

1)安裝Crane

go install github.com/google/go-containerregistry/cmd/crane@latest

https://github.com/google/go-containerregistry/blob/main/cmd/crane/doc/crane.md

在go-containerregistry的crane的文件目錄中,有crane的詳細文件。

2)crane命令

對於容器映象下載功能來說,就是執行crane pull <映象全名>這個命令

2、2 crane 映象下載API

我最關心的是下載映象功能,也就是crane pull命令以及其對應的api。

映象下載的API包括:

  • Pull函式
  • SaveLegacy或SaveOCI函式
func Pull(src string, opt ...Option) (v1.Image, error)

Pull 函式返回遠端映象 src 的 v1.Image。src引數為映象的全程,如alpine:latest

func SaveLegacy(img v1.Image, src, path string) error

SaveLegacy 將 img指定的映象內容寫為tarball壓縮包,路徑為path

func SaveOCI(img v1.Image, path string) error

SaveOCI 將 img 指定的映象內容以 OCI 映象格式寫入path路徑上。

三、crane下載容器映象demo

func DownloadImage(imageFullName string) {
   var (
      image v1.Image
      err   error
   )

   //1.從遠端倉庫拉取映象
   image, err = crane.Pull(imageFullName)
   if err != nil {
      fmt.Println("crane.Pull function failed")
      return
   }

   //2.獲取映象的雜湊值
   m, err := image.Manifest()
   imageFullHash := m.Config.Digest.Hex
   fmt.Println("image hash:", imageFullHash)

   //3.建立映象儲存路徑
   imageStorageDir := "/tmp" //預設值為tmp目錄
   err = os.MkdirAll(imageStorageDir, 0755)
   if err != nil {
      fmt.Printf("mkdir %s failed!\n")
      return
   }
   imagePath := imageStorageDir + "/package.tar"

   //4.儲存映象到儲存路徑,SaveLegacy儲存的映象格式為tarball
   //你也可採用SaveOCI函式完成這個功能
   err = crane.SaveLegacy(image, src, imagePath)
   if err != nil {
      fmt.Println("crane.SaveLegacy function failed")
      return
   }
}

使用crane下載映象很簡單,分為以下三步

1、從遠端倉庫拉取映象資訊

2、建立映象儲存路徑

3、儲存映象到儲存路徑

四、映象包格式探祕

備註:go-containerregistry的tarball格式是有別於OCI規範的。

4、1 映象包的組織形式

上面的demo程式成功下載alpine:latest映象,並存儲到/tmp/packaget.tar後我們解壓packaget.tar,如下圖所示:

[root@t440s package]# tree
.
├── 47d7af55c64c2611fde7f765c544f305238fb7c7fd7d5118e170202f887e9987
│ ├── json
│ ├── layer.tar
│ └── VERSION
├── c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18.json
├── manifest.json
└── repositories

1 directory, 6 files

manifest.json檔案:在最頂層,有一個manifest.json檔案包含多個映象的資訊
對於每個層(layer),都會以映象層 ID作為目錄,目錄中包含以下內容:
layer.tar - 未壓縮的層 tar包
json - 以Layer ID命名的json檔案,包含Layer層的元資料
VERSION - 版本字串,始終設定為1.0

c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18.json :映象描述檔案

4、2 檔案內容

下面我們依次剖析以下檔案

manifest.json

映象描述檔案

Layer映象層資料

repositories檔案

1) manifest.json檔案

manifest.json 檔案中內容如下所示:

[{
	"Config": "c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18.json",
	"RepoTags": ["alpine:latest"],
	"Layers": ["47d7af55c64c2611fde7f765c544f305238fb7c7fd7d5118e170202f887e9987/layer.tar"]
}]

其欄位解釋如下:

Config:配置檔案路徑

Layers:指明瞭Layer層檔案的儲存路徑

RepoTags:映象的名稱,帶有標籤

其所有路徑都是相當於manifest.json檔案路徑的相對路徑。

2) 映象描述檔案

映象描述檔案是上面的c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18.json檔案

其json結構如下所示:

{
	"architecture": "amd64", #架構
	"config": {
		"Hostname": "",
		"Domainname": "",
		"User": "",
		"AttachStdin": false,
		"AttachStdout": false,
		"AttachStderr": false,
		"Tty": false,
		"OpenStdin": false,
		"StdinOnce": false,
		"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
		"Cmd": ["/bin/sh"],
		"Image": "sha256:b747534ae29d08c0c84cc4326caf04e873c6d02bb67cd9c7644be2b4fa8d2f31",
		"Volumes": null,
		"WorkingDir": "",
		"Entrypoint": null,
		"OnBuild": null,
		"Labels": null
	},
	"container": "4292e8ed2ef2b6dc4bbaf8e1cda0cb5f95b96adc4aa2da3d15181b54d07a0b34",
	"container_config": {
		"Hostname": "4292e8ed2ef2",
		"Domainname": "",
		"User": "",
		"AttachStdin": false,
		"AttachStdout": false,
		"AttachStderr": false,
		"Tty": false,
		"OpenStdin": false,
		"StdinOnce": false,
		"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
		"Cmd": ["/bin/sh", "-c", "#(nop) ", "CMD [\"/bin/sh\"]"],
		"Image": "sha256:b747534ae29d08c0c84cc4326caf04e873c6d02bb67cd9c7644be2b4fa8d2f31",
		"Volumes": null,
		"WorkingDir": "",
		"Entrypoint": null,
		"OnBuild": null,
		"Labels": {}
	},
	"created": "2021-11-24T20:19:40.483367546Z",
	"docker_version": "20.10.7",
	"history": [{
		"created": "2021-11-24T20:19:40.199700946Z",
		"created_by": "/bin/sh -c #(nop) ADD file:9233f6f2237d79659a9521f7e390df217cec49f1a8aa3a12147bbca1956acdb9 in / "
	}, {
		"created": "2021-11-24T20:19:40.483367546Z",
		"created_by": "/bin/sh -c #(nop)  CMD [\"/bin/sh\"]",
		"empty_layer": true
	}],
	"os": "linux",
	"rootfs": {
		"type": "layers",
		"diff_ids": ["sha256:8d3ac3489996423f53d6087c81180006263b79f206d3fdec9e66f0e27ceb8759"]
	}
}

包含作業系統、容器配置、rootfs、建立時間、系統架構等資訊。

3) Layer映象層資料

由manifest.json檔案的Layers欄位可知,映象層資料的儲存路徑為47d7af55c64c2611fde7f765c544f305238fb7c7fd7d5118e170202f887e9987/layer.tar

將layer.tar包建立資料夾layer並進行解壓:

mkdir layer
tar xvf layer.tar -C layer

具備啟動一個系統所需要的最小檔案系統。

4) repositories檔案

{
	"alpine": {
		"latest": "47d7af55c64c2611fde7f765c544f305238fb7c7fd7d5118e170202f887e9987"
	}
}

描述映象的名稱和tag以及sha值。

五、總結

今天我們學習了go-containerregistry庫中使用crane來進行容器映象下載,將下載的映象儲存成tar包格式,並瞭解了映象包的格式,以及內部的檔案組織形式。

參考資料:

https://aliyun123.cn/2299.html

本文由部落格一文多發平臺 OpenWrite 釋出!