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

go-containerregistry 实战篇之容器镜像下载

具备启动一个系统所需要的最小文件系统。

4) repositories文件

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

描述镜像的名称和tag以及sha值。

五、总结

今天我们学习了go-containerregistry库中使用crane来进行容器镜像下载,将下载的镜像保存成tar包格式,并了解了镜像包的格式,以及内部的文件组织形式。

参考资料:

https://aliyun123.cn/2299.html

本文由博客一文多发平台 OpenWrite 发布!

Original: https://www.cnblogs.com/codergeek/p/15967758.html
Author: codergeek
Title: go-containerregistry 实战篇之容器镜像下载

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516412/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • golang 实现一个简单的命令行进度条

    由于有时候跑脚本几个小时看不到进度,所以想着写一个简单的命令行的进度条。类似下面这样的 其中的原理主要是\r回车符(将光标移动到行首)。这样的话就可以重新打印一行以覆盖之前的那一行…

    Go语言 2023年5月25日
    052
  • 使用Go http重试请求

    原文连接:https://www.zhoubotong.site/post/78.html开发中对于http请求是经常遇到,一般可能网络延迟或接口返回超时,对于发起客户端的请求, …

    Go语言 2023年5月25日
    054
  • Sentinel-Go 源码系列(一)|开篇

    大家好呀,打算写一个 Go 语言组件源码分析系列,一是为了能学习下 Go 语言,看下别人是怎么写 Go 的,二是也掌握一个组件。 本次选择了 Sentinel-Go,一是对 Jav…

    Go语言 2023年5月25日
    067
  • Go语言之反射

    一、反射的基本概念 (一)什么是反射 反射可以再运行时动态获取变量的各种信息,比如变量的类型、值等 如果时结构体变量,还可以获取到结构体本身的各种信息,比如结构体的字段、方法 通过…

    Go语言 2023年5月29日
    076
  • Go语言之如何给*int32类型赋值

    直接上代码: package main import “fmt” func main () { var num *int32 var i int32 = 5…

    Go语言 2023年5月29日
    055
  • go微服务框架Kratos笔记(二)引入zap日志库

    zap日志库是一款高性能的开源日志库,提供了结构化日志记录和printf风格的日志记录 go get -u go.uber.org/zap 参考官方文档中描述,为了方便业务自适配不…

    Go语言 2023年5月25日
    054
  • 第十五章:指针类型

    本篇翻译自《Practical Go Lessons》 Chapter 15: Pointer type 1 你将在本章将学到什么? 什么是指针? 什么时指针类型? 如何去创建并使…

    Go语言 2023年5月25日
    062
  • 基于Go语言实现好用的HTTP接口请求requests

    使用Go自带的net/http库可以发送各种HTTP请求。然而各种类型请求发送方式有点不太一致,这里参考Python requests库的使用方式,简单封装了一下。代码如下: 文件…

    Go语言 2023年5月29日
    061
  • 大道如青天,协程来通信,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang通道channel的使用EP14

    众所周知,Go lang的作用域相对严格,数据之间的通信往往要依靠参数的传递,但如果想在多个协程任务中间做数据通信,就需要通道(channel)的参与,我们可以把数据封装成一个对象…

    Go语言 2023年5月25日
    087
  • Excelize 2.5.0 正式发布,这些新增功能值得关注

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Mic…

    Go语言 2023年5月25日
    067
  • 通过Go语言创建CA与签发证书

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Go语言 2023年5月25日
    063
  • go-micro集成RabbitMQ实战和原理

    在go-micro中异步消息的收发是通过Broker这个组件来完成的,底层实现有RabbitMQ、Kafka、Redis等等很多种方式,这篇文章主要介绍go-micro使用Rabb…

    Go语言 2023年5月25日
    067
  • 盘点Go中的开发神器

    本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 在Java中,我们用Junit做单元测试,用JMH做性能基准测试(benc…

    Go语言 2023年5月25日
    078
  • Go内存逃逸分析

    Go的内存逃逸及逃逸分析 Go的内存逃逸 分析内存逃逸之前要搞清楚一件事 我们编写的程序中的 函数和 局部变量默认是存放在栈上的(补充一点堆上存储的数据的指针 是存放在栈上的 因为…

    Go语言 2023年5月25日
    047
  • 服务注册与发现的原理和实现

    什么是服务注册发现? 对于搞微服务的同学来说,服务注册、服务发现的概念应该不会太陌生。 简单来说,当服务A需要依赖服务B时,我们就需要告诉服务A,哪里可以调用到服务B,这就是服务注…

    Go语言 2023年5月25日
    056
  • Go编译过程

    一、 Go编译流程 二、过程说明 词法解析 读取Go源文件,将字符序列转换为符号(token)序列,比如将”:=”转换为_Define 代码中的标识符、关键…

    Go语言 2023年5月25日
    062
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球