- 云原生
【免费下载链接】buildah
A tool that facilitates building OCI images.
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),其功能由四个子命令承担:
| 子命令 | 手册页 | 功能 |
|---|---|---|
add | buildah-source-add(1) | 向源镜像添加一个源构件 |
create | buildah-source-create(1) | 创建并初始化一个源镜像 |
pull | buildah-source-pull(1) | 从 registry 拉取源镜像到指定路径 |
push | buildah-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-value | true | 是否在镜像 config 中写入 "created" 时间戳 |
底层实现
create对应 internal/source/create.go 中的Create函数,流程如下:
- 前置校验:
fileutils.Exists(sourcePath)检查目标路径是否已存在——已存在则直接报错"creating source image: %q already exists"(create.go)。这与pull的约束一致:源镜像目录必须从零创建。 - 打开/创建 OCI 布局:
openOrCreateSourceImage内部通过layout.ParseReference(sourcePath)+NewImageDestination在目标路径隐式创建完整的 OCI 目录布局(oci-layout、index.json、blobs/),见 source.go。 - 写入 config blob:
addConfig将ImageConfig{Author, Created}序列化为 JSON 后通过PutBlob写入blobs/sha256/(source.go)。 - 写入 manifest:构造 schemaVersion=2 的 OCI manifest,其
Config.MediaType固定为MediaTypeSourceImageConfig,Config.Digest/Size指向刚写入的 config blob(create.go)。 - 提交:
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)的执行流程:
- 校验
sourcePath必须已存在(区别于create)。 - 解析
--annotation为 map。 - 使用
archive.TarWithOptions(artifactPath, &archive.TarOptions{Compression: archive.Gzip})生成 gzip 压缩的 tar 流(add.go),对应手册中"gzip-compressed tar ball"的表述。 - 通过
PutBlob将压缩流写入源镜像,得到 blob 的 digest/size。 - 读取现有 manifest,把新构件作为一层追加:
MediaType为application/vnd.oci.image.layer.v1.tar+gzip,并携带注解(add.go)。 - 写回新 manifest 后,删除旧 manifest blob(
removeBlob,按blobs/sha256/<digest>的固定路径删除,见 source.go)。 - 最后用
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,-q | false | 抑制拉取源镜像时的进度输出 |
--tls-verifybool-value | true | 与容器 registry 通信时要求 HTTPS 并验证证书;不可用于不安全的 registry |
底层实现
Pull函数(internal/source/pull.go):
- 目标路径
sourcePath必须不存在,否则报错(pull.go)。 - 镜像引用解析:
stringToImageReference使用docker://transport;不支持短名(short name)拉取,必须使用完全限定名(fully-qualified name),见 pull.go。 - 构建
types.SystemContext:TLSVerify=false时设置DockerInsecureSkipTLSVerify;--creds非空时调用parse.AuthConfig填充DockerAuthConfig(pull.go)。 - 合规校验:
validateSourceImageReference读取远端 manifest,检查ociManifest.Config.MediaType必须等于MediaTypeSourceImageConfig,否则报错invalid media type of image config ... (expected: ...)(pull.go)。这就是手册所述"不符合 source-image artifact 则拉取失败"的机制。 - 获取默认签名策略(
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,-q | false | 抑制推送源镜像时的进度输出 |
--tls-verifybool-value | true | 与容器 registry 通信时要求 HTTPS 并验证证书;不可用于不安全的 registry |
底层实现
Push函数(internal/source/push.go):
- 源引用通过
layout.ParseReference(sourcePath)从本地 OCI 布局解析,目标引用经stringToImageReference转为docker://引用。 SystemContext的构建与pull一致:DockerInsecureSkipTLSVerify对应--tls-verify,DockerAuthConfig对应--creds(push.go)。- 在签名策略上下文中执行
copy.Image,进度输出到 stderr(非--quiet)。 - 若指定
--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.
相关推荐
OpenShift Source-to-Image (S2I) 命令行工具完全指南
OpenShift Source to Image S2I 命令行工具完全指南 什么是Source to Image S2I Source to Image S
开发工具云原生WeChatTweak底层架构:macOS微信客户端的二进制补丁机制实现
WeChatTweak底层架构:macOS微信客户端的二进制补丁机制实现 WeChatTweak是一个针对macOS微信客户端的命令行工具,通过Mach O二进
逆向工程CLI即时通讯Argo CD 源码完整性管理:argocd proj source-integrity git policies update 命令完全指南
Argo CD 源码完整性管理:argocd proj source integrity git policies update 命令完全指南 本指南围绕 Ar
云原生CI/CD容器编排DevOps后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考