基于 skopeo(containers库) 二次开发 Go 代码示例

系列文章目录

skopeo工具安装部署
skopeo 基本命令
基于 skopeo(containers库) 二次开发 Go 代码示例

一、skopeo 是什么?

skopeo是一个命令行工具,可以对容器镜像和镜像仓库执行各种操作。
skopeo不要求用户以root身份运行来执行其大部分操作。
skopeo不需要运行守护进程来执行其操作。
skopeo可以使用OCI镜像以及原始的Docker v2镜像。

skopeo 是基于 containers/image 库 研发的二进制工具,如果你想要将 skopeo 工具的功能集成到自己的平台当中,可以考虑引入 containers/image 库 库,下面是 Go 代码示例。

二、Go 代码示例

main.go 文件

代码如下(示例):


package main

import (
	"context"
	"fmt"
	"path/filepath"
	"strings"

	"github.com/containers/image/v5/copy"
	"github.com/containers/image/v5/directory"
	"github.com/containers/image/v5/docker"
	"github.com/containers/image/v5/signature"
	"github.com/containers/image/v5/types"
)

func main() {
	// 设置镜像的URL
	imageUrl := "iregistry.baidu-int.com/tianniu/zhaikaifang/get-cpu-os:v1-amd64"

	// 将URL中的斜杠替换为@符号,作为保存的文件名
	imageSaveName := strings.ReplaceAll(imageUrl, "/", "@")

	// 设置保存镜像的完整路径
	savePath := filepath.Join("/tmp", "images", imageSaveName)

	// 调用函数ImagePullAsDir来拉取镜像并保存为目录
	if err := ImagePullAsDir(context.Background(), imageUrl, savePath, "", ""); err != nil {
		// 如果拉取镜像过程中发生错误,则抛出异常
		panic(err)
	} else {
		fmt.Printf("%s pull success!\n", imageUrl)
	}

	// 调用函数ImagePushAsDir来推送镜像到registry
	// 注:user 和 password 参数为registry的登录信息
	if err := ImagePushAsDir(context.Background(), imageUrl, savePath, "xxxx", "xxxx"); err != nil {
		// 如果推送镜像过程中发生错误,则抛出异常
		panic(err)
	} else {
		fmt.Printf("%s push success!\n", imageUrl)
	}
}

// ImagePullAsDir 拉取镜像到目录
func ImagePullAsDir(ctx context.Context, imageUrl, savePath, user, password string) error {
	// 创建一个签名策略上下文
	policy, err := signature.NewPolicyContext(&signature.Policy{
		Default: []signature.PolicyRequirement{signature.NewPRInsecureAcceptAnything()},
	})
	if err != nil {
		return err
	}

	// 解析镜像URL为引用对象
	srcRef, err := docker.Transport.ParseReference("//" + imageUrl)
	if err != nil {
		return err
	}

	// 解析保存路径为引用对象
	destRef, err := directory.Transport.ParseReference(savePath)
	if err != nil {
		return err
	}

	// 设置源系统上下文
	sourceCtx := &types.SystemContext{
		DockerInsecureSkipTLSVerify: types.NewOptionalBool(true),
		DockerAuthConfig: &types.DockerAuthConfig{
			Username: user,
			Password: password,
		},
		OSChoice:           "linux",
		ArchitectureChoice: "amd64",
	}

	// 设置目标系统上下文
	destinationCtx := &types.SystemContext{}

	// 复制镜像
	_, err = copy.Image(ctx, policy, destRef, srcRef, &copy.Options{
		ReportWriter:   nil,
		SourceCtx:      sourceCtx,
		DestinationCtx: destinationCtx,
		// ImageListSelection: copy.CopyAllImages, 如果拉取多架构镜像,则设置该参数
	})
	if err != nil {
		return err
	}

	return nil
}

// ImagePushAsDir 推送目录格式镜像到registry
func ImagePushAsDir(ctx context.Context, imageUrl, savePath, user, password string) error {
	// 创建一个签名策略上下文
	policy, err := signature.NewPolicyContext(&signature.Policy{
		Default: []signature.PolicyRequirement{signature.NewPRInsecureAcceptAnything()},
	})
	if err != nil {
		return err
	}

	// 解析目标镜像的引用
	destRef, err := docker.Transport.ParseReference("//" + imageUrl)
	if err != nil {
		return err
	}

	// 解析源目录的引用
	srcRef, err := directory.Transport.ParseReference(savePath)
	if err != nil {
		return err
	}

	// 设置推送镜像的上下文信息
	destinationCtx := &types.SystemContext{
		DockerInsecureSkipTLSVerify: types.NewOptionalBool(true),
		DockerAuthConfig: &types.DockerAuthConfig{
			Username: user,
			Password: password,
		},
		OSChoice: "linux",
		// 期望推送的镜像架构类型是 amd64
		ArchitectureChoice: "amd64",
	}

	// 设置源目录的上下文信息
	sourceCtx := &types.SystemContext{}

	// 执行镜像的复制操作,实际上是推送镜像
	_, err = copy.Image(ctx, policy, destRef, srcRef, &copy.Options{
		ReportWriter:   nil,
		SourceCtx:      sourceCtx,
		DestinationCtx: destinationCtx,
	})
	if err != nil {
		return err
	}

	return nil
}

go.mod 文件

代码如下(示例):

module go-personal/skopeo-golang

go 1.21

require github.com/containers/image/v5 v5.31.1

require (
	github.com/BurntSushi/toml v1.3.2 // indirect
	github.com/VividCortex/ewma v1.2.0 // indirect
	github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
	github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
	github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
	github.com/containers/ocicrypt v1.1.10 // indirect
	github.com/containers/storage v1.54.0 // indirect
	github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
	github.com/distribution/reference v0.6.0 // indirect
	github.com/docker/distribution v2.8.3+incompatible // indirect
	github.com/docker/docker v26.1.3+incompatible // indirect
	github.com/docker/docker-credential-helpers v0.8.1 // indirect
	github.com/docker/go-connections v0.5.0 // indirect
	github.com/docker/go-units v0.5.0 // indirect
	github.com/go-jose/go-jose/v3 v3.0.3 // indirect
	github.com/go-openapi/analysis v0.23.0 // indirect
	github.com/go-openapi/errors v0.22.0 // indirect
	github.com/go-openapi/jsonpointer v0.21.0 // indirect
	github.com/go-openapi/jsonreference v0.21.0 // indirect
	github.com/go-openapi/loads v0.22.0 // indirect
	github.com/go-openapi/runtime v0.28.0 // indirect
	github.com/go-openapi/spec v0.21.0 // indirect
	github.com/go-openapi/strfmt v0.23.0 // indirect
	github.com/go-openapi/swag v0.23.0 // indirect
	github.com/go-openapi/validate v0.24.0 // indirect
	github.com/golang/protobuf v1.5.4 // indirect
	github.com/google/go-containerregistry v0.19.1 // indirect
	github.com/google/uuid v1.6.0 // indirect
	github.com/gorilla/mux v1.8.1 // indirect
	github.com/josharian/intern v1.0.0 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/klauspost/compress v1.17.8 // indirect
	github.com/klauspost/pgzip v1.2.6 // indirect
	github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/mattn/go-runewidth v0.0.15 // indirect
	github.com/mattn/go-sqlite3 v1.14.22 // indirect
	github.com/miekg/pkcs11 v1.1.1 // indirect
	github.com/mitchellh/mapstructure v1.5.0 // indirect
	github.com/moby/sys/mountinfo v0.7.1 // indirect
	github.com/moby/sys/user v0.1.0 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/oklog/ulid v1.3.1 // indirect
	github.com/opencontainers/go-digest v1.0.0 // indirect
	github.com/opencontainers/image-spec v1.1.0 // indirect
	github.com/opencontainers/runtime-spec v1.2.0 // indirect
	github.com/proglottis/gpgme v0.1.3 // indirect
	github.com/rivo/uniseg v0.4.7 // indirect
	github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
	github.com/sigstore/fulcio v1.4.5 // indirect
	github.com/sigstore/rekor v1.3.6 // indirect
	github.com/sigstore/sigstore v1.8.3 // indirect
	github.com/sirupsen/logrus v1.9.3 // indirect
	github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
	github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
	github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
	github.com/ulikunitz/xz v0.5.12 // indirect
	github.com/vbatts/tar-split v0.11.5 // indirect
	github.com/vbauerster/mpb/v8 v8.7.3 // indirect
	go.mongodb.org/mongo-driver v1.14.0 // indirect
	go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
	golang.org/x/crypto v0.23.0 // indirect
	golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
	golang.org/x/net v0.25.0 // indirect
	golang.org/x/sync v0.7.0 // indirect
	golang.org/x/sys v0.20.0 // indirect
	golang.org/x/term v0.20.0 // indirect
	golang.org/x/text v0.15.0 // indirect
	google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
	google.golang.org/grpc v1.62.1 // indirect
	google.golang.org/protobuf v1.33.0 // indirect
	gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)

执行结果截图

总结

这里仅仅是使用 Go 代码调用了 containers/image 库,做的一个 demo 示例,方便用户快速入手,更多功能还需要看下 containers/image 库的源码,也可以使用 skopeo 工具,熟悉功能,进而调用 containers/image 功能复用到自己平台当中。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
A*算法是一种常用的启发式搜索算法,用于求解图的最短路径问题。它结合了广度优先搜索和启发式搜索的特点,能够高效地找到最优路径。 下面是一个基于A*算法的Matlab代码示例: ```matlab function path = aStarAlgorithm(graph, start, goal) openList = PriorityQueue(); % 创建一个优先队列用于存放待扩展的节点 openList.insert(start, 0); % 将起始节点加入openList中 cameFrom = containers.Map; % 存放节点的父节点,用于回溯路径 gScore = containers.Map; % 存放节点的实际代价 gScore(start) = 0; % 起始节点的实际代价为0 fScore = containers.Map; % 存放节点的估计代价 fScore(start) = heuristicCostEstimate(start, goal); % 起始节点的估计代价为启发式函数值 while ~openList.isEmpty() current = openList.pop(); % 从openList中取出fScore最小的节点 if current == goal path = reconstructPath(cameFrom, goal); % 回溯路径 return; end neighbors = getNeighbors(graph, current); % 获取当前节点的邻居节点 for i = 1:length(neighbors) neighbor = neighbors(i); tentativeGScore = gScore(current) + distance(current, neighbor); % 计算从起始节点到邻居节点的实际代价 if ~isKey(gScore, neighbor) || tentativeGScore < gScore(neighbor) cameFrom(neighbor) = current; gScore(neighbor) = tentativeGScore; fScore(neighbor) = gScore(neighbor) + heuristicCostEstimate(neighbor, goal); if ~openList.contains(neighbor) openList.insert(neighbor, fScore(neighbor)); % 将邻居节点加入openList中 end end end end end ``` 以上代码是一个简单的A*算法实现,其中包括了节点的存储、优先队列的使用、启发式函数的定义等基本步骤。通过这个示例,我们可以看到A*算法的基本思想和实现方式,能够帮助我们更好地理解和应用这个经典的搜索算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

k8s-open

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值