系列文章目录
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, ©.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, ©.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 功能复用到自己平台当中。