☰
buildah source 子命令完全指南:创建、管理并分发 OCI Source Image
2026/9/25 4:16:59 网站建设 项目流程
  • 云原生

【免费下载链接】buildah

A tool that facilitates building OCI images.

项目地址:https://gitcode.com/gh_mirrors/bu/buildah
点击查看免费下载

buildah source是 Buildah 提供的实验性子命令组,用于创建、推送、拉取和管理**源镜像(source image)**及其关联的源构件(source artifact)。本文以 docs/buildah-source.1.md 为主线,结合 internal/source 下的源码实现,完整讲解 source 镜像的概念、四个子命令(create、add、pull、push)的用法、全部命令行选项与底层工作原理,帮助读者理解如何把构建普通 OCI 镜像所用的全部源代码(SRPM、源码树、文本文件等)打包成可分发、可追溯的源镜像。

什么是 source image(源镜像)

根据 docs/buildah-source.1.md 的定义,source image 是一种包含构建普通 OCI 镜像所用到的全部源构件的镜像。这些构件可以是任何类型的源代码产物,例如:

  • 源码 RPM(source RPM)
  • 完整的源码树(entire source tree)
  • 文本文件

换句话说,普通 OCI 镜像交付的是"构建结果"(二进制、库、运行时),而 source image 交付的是"构建依据"(源码与原材料),两者一一对应,为合规审计、可复现构建(reproducible build)与供应链溯源提供基础。

从 internal/source/source.go 的实现看,source image 在 OCI 规范层面是一个OCI artifact:

// MediaTypeSourceImageConfig specifies the media type of a source-image config. const MediaTypeSourceImageConfig = "application/vnd.oci.source.image.config.v1+json"

它本质上仍是 OCI v1 manifest 镜像,但 config 部分使用自定义媒体类型application/vnd.oci.source.image.config.v1+json,这是区分"普通镜像"与"源镜像"的关键标记。对应的 config 结构(source.go)只包含两个字段:

type ImageConfig struct { // Created 是层创建的日期与时间,按 RFC 3339 第 5.6 节格式定义。 Created *time.Time `json:"created,omitempty"` // Author 是源镜像的作者。 Author string `json:"author,omitempty"` }

实验性声明

buildah source及其所有子命令目前都是实验性功能,未来可能发生变化(该声明同时出现在主手册页和每个子命令手册页中)。生产环境集成前请评估版本兼容性,本文描述的行为以当前仓库代码为准。

命令总览

buildah source主命令本身不接受具体操作(RunE直接返回 nil,见 cmd/buildah/source.go),其功能由四个子命令承担:

子命令手册页功能
addbuildah-source-add(1)向源镜像添加一个源构件
createbuildah-source-create(1)创建并初始化一个源镜像
pullbuildah-source-pull(1)从 registry 拉取源镜像到指定路径
pushbuildah-source-push(1)从指定路径推送源镜像到 registry

四个子命令的参数个数与典型用法示例如下(来自 source.go 中的 cobra 定义与 Example 字段):

# create:路径参数必须不存在(cobra.ExactArgs(1)) buildah source create /tmp/fedora:latest-source # add:两个参数——源镜像路径 + 源构件(cobra.ExactArgs(2)) buildah source add /tmp/fedora sources.tar.gz # pull:两个参数——registry 上的镜像名 + 本地目标路径(cobra.ExactArgs(2)) buildah source pull quay.io/sourceimage/example:latest /tmp/sourceimage:latest # push:两个参数——本地源镜像路径 + registry 上的目标镜像名(cobra.ExactArgs(2)) buildah source push /tmp/sourceimage:latest quay.io/sourceimage/example:latest

子命令 1:buildah source create

用途:创建并初始化一个 source image,也就是生成一个采用自定义 config 媒体类型的 OCI artifact。

语法(docs/buildah-source-create.1.md):

buildah source create [options] path

选项:

选项默认值说明
--authorauthor空(不设置)在 config 中设置源镜像作者
--time-stampbool-valuetrue是否在镜像 config 中写入 "created" 时间戳

底层实现

create对应 internal/source/create.go 中的Create函数,流程如下:

  1. 前置校验:fileutils.Exists(sourcePath)检查目标路径是否已存在——已存在则直接报错"creating source image: %q already exists"(create.go)。这与pull的约束一致:源镜像目录必须从零创建。
  2. 打开/创建 OCI 布局:openOrCreateSourceImage内部通过layout.ParseReference(sourcePath)+NewImageDestination在目标路径隐式创建完整的 OCI 目录布局(oci-layout、index.json、blobs/),见 source.go。
  3. 写入 config blob:addConfig将ImageConfig{Author, Created}序列化为 JSON 后通过PutBlob写入blobs/sha256/(source.go)。
  4. 写入 manifest:构造 schemaVersion=2 的 OCI manifest,其Config.MediaType固定为MediaTypeSourceImageConfig,Config.Digest/Size指向刚写入的 config blob(create.go)。
  5. 提交:ociDest.Commit(ctx, nil)完成布局提交。

关于--time-stamp:对应CreateOptions.TimeStamp字段。为false时createdTime()返回nil,config JSON 中created字段因omitempty被省略(create.go)。--author则直接写入 config 的author字段。两个选项在 CLI 层的绑定见 cmd/buildah/source.go。

子命令 2:buildah source add

用途:向已存在的源镜像添加一个源构件。构件会以gzip 压缩的 tar 包形式加入,且只有必要时才做自动 tar / 自动压缩(即 tar 包直接使用,普通文件自动打包)。

语法(docs/buildah-source-add.1.md):

buildah source add [options] path artifact

选项:

选项默认值说明
--annotationkey=value无为源镜像 manifest 中的该层 descriptor 添加注解,输入格式为key=value

--annotation可重复使用(CLI 层用StringArrayVar绑定,见 source.go),每次给层添加一条注解。解析逻辑在 internal/source/add.go:

  • 每个注解必须包含=,否则报错invalid annotation ... (expected format is "key=value");
  • 同一个 key 只能指定一次,重复会报错annotation ... specified more than once;
  • 解析结果以map[string]string形式写入该层 descriptor 的Annotations字段。

底层实现

Add函数(add.go)的执行流程:

  1. 校验sourcePath必须已存在(区别于create)。
  2. 解析--annotation为 map。
  3. 使用archive.TarWithOptions(artifactPath, &archive.TarOptions{Compression: archive.Gzip})生成 gzip 压缩的 tar 流(add.go),对应手册中"gzip-compressed tar ball"的表述。
  4. 通过PutBlob将压缩流写入源镜像,得到 blob 的 digest/size。
  5. 读取现有 manifest,把新构件作为一层追加:MediaType为application/vnd.oci.image.layer.v1.tar+gzip,并携带注解(add.go)。
  6. 写回新 manifest 后,删除旧 manifest blob(removeBlob,按blobs/sha256/<digest>的固定路径删除,见 source.go)。
  7. 最后用updateIndexWithNewManifestDescriptor重写index.json,使index.Manifests指向最新 manifest descriptor(add.go)。

这一"新 manifest 生效、旧 manifest 删除"的设计,保证源镜像目录始终只保留一份当前有效的 manifest。

子命令 3:buildah source pull

用途:从 registry 将源镜像拉取到指定本地路径。若镜像不符合 source-image OCI artifact 规范,拉取将直接失败。

语法(docs/buildah-source-pull.1.md):

buildah source pull [options] registry path

选项:

选项默认值说明
--credscreds无访问 registry 的认证信息[username[:password]];若用户名或密码缺失,会弹出命令行提示输入(密码不回显)
--quiet,-qfalse抑制拉取源镜像时的进度输出
--tls-verifybool-valuetrue与容器 registry 通信时要求 HTTPS 并验证证书;不可用于不安全的 registry

底层实现

Pull函数(internal/source/pull.go):

  1. 目标路径sourcePath必须不存在,否则报错(pull.go)。
  2. 镜像引用解析:stringToImageReference使用docker://transport;不支持短名(short name)拉取,必须使用完全限定名(fully-qualified name),见 pull.go。
  3. 构建types.SystemContext:TLSVerify=false时设置DockerInsecureSkipTLSVerify;--creds非空时调用parse.AuthConfig填充DockerAuthConfig(pull.go)。
  4. 合规校验:validateSourceImageReference读取远端 manifest,检查ociManifest.Config.MediaType必须等于MediaTypeSourceImageConfig,否则报错invalid media type of image config ... (expected: ...)(pull.go)。这就是手册所述"不符合 source-image artifact 则拉取失败"的机制。
  5. 获取默认签名策略(signature.DefaultPolicy)后,通过copy.Image将镜像复制到layout.ParseReference(sourcePath)解析出的 OCI 布局目标;非--quiet模式下进度输出到 stderr(pull.go)。

子命令 4:buildah source push

用途:将指定本地路径的源镜像推送到 registry。

语法(docs/buildah-source-push.1.md):

buildah source push [options] path registry

选项:

选项默认值说明
--credscreds无访问 registry 的认证信息[username[:password]];缺省部分会交互式提示(密码不回显)
--digestfiledigestfile无镜像复制完成后,将结果镜像的 digest 写入指定文件
--quiet,-qfalse抑制推送源镜像时的进度输出
--tls-verifybool-valuetrue与容器 registry 通信时要求 HTTPS 并验证证书;不可用于不安全的 registry

底层实现

Push函数(internal/source/push.go):

  1. 源引用通过layout.ParseReference(sourcePath)从本地 OCI 布局解析,目标引用经stringToImageReference转为docker://引用。
  2. SystemContext的构建与pull一致:DockerInsecureSkipTLSVerify对应--tls-verify,DockerAuthConfig对应--creds(push.go)。
  3. 在签名策略上下文中执行copy.Image,进度输出到 stderr(非--quiet)。
  4. 若指定--digestfile,则用manifest.Digest(manifestBytes)计算推送后镜像 manifest 的 digest,并以 0644 权限写入文件(push.go)。该 digest 可用于后续的拉取验证或签名引用。

典型工作流:从源码到可追溯分发

结合上述四个子命令与 internal/source 的实现,一条完整的源镜像生命周期如下:

# 1. 初始化源镜像(本地将生成标准 OCI 目录布局) buildah source create --author "CI Bot <ci@example.com>" ./src-image # 2. 逐个添加源构件(自动 tar+gzip;可用 --annotation 标注元信息) buildah source add --annotation "type=source-rpm" ./src-image ./fedora-source.rpm buildah source add --annotation "path=/" ./src-image ./source-tree/ # 3. 推送到 registry,并保存 digest 供后续验证 buildah source push --digestfile ./src-image.digest ./src-image quay.io/example/app:source # 4. 在另一环境拉取(必须是完全限定名;非源镜像会失败) buildah source pull --quiet quay.io/example/app:source ./recovered-src

需要留意两个易错点:create与pull的目标路径都必须尚不存在(源码中均有显式检查);pull不支持短名,必须提供完整的 registry 镜像名。

扩展阅读

  • 子命令手册: buildah-source-add(1) 、 buildah-source-create(1) 、 buildah-source-pull(1) 、 buildah-source-push(1)
  • CLI 层实现与全部 flag 绑定:cmd/buildah/source.go
  • 核心库实现:internal/source/source.go(媒体类型、manifest/config 读写、blob 管理)、 internal/source/create.go 、 internal/source/add.go 、 internal/source/pull.go 、 internal/source/push.go
  • 父命令手册:docs/buildah.1.md
  • 云原生

【免费下载链接】buildah

A tool that facilitates building OCI images.

项目地址:https://gitcode.com/gh_mirrors/bu/buildah
点击查看免费下载
上一篇:mambaout_femto.in1k迁移学习教程:自定义数据集训练完整流程
下一篇:Android-ObservableScrollView与Jetpack组件协同开发

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询