云原生【免费下载链接】buildahA tool that facilitates building OCI images.项目地址https://gitcode.com/gh_mirrors/bu/buildah点击查看免费下载本教程基于 Buildah 官方教程第 4 篇整理并扩充演示如何把 Buildah 当作 Go 库嵌入你自己的构建工具中从而复用其完整的镜像构建能力——包括读取 Dockerfile/Containerfile、执行 RUN 指令以及 rootless无 root构建。文中以创建一个内置 Node.js 运行时与 JS 入口文件的镜像为贯穿示例从项目引导、依赖安装到代码编写与运行并结合当前仓库源码逐层拆解Builder、storage.Store、Commit、rootless 重执行等关键机制帮助你掌握用 Buildah 库构建自定义构建系统的完整套路。为什么要把 Buildah 作为库使用Buildah 不只是一条buildah bud命令行工具它的核心能力全部沉淀在 Go 包go.podman.io/buildah中。你在命令行里能做的所有事情——从镜像拉取、基于 Dockerfile 构建、RUN 阶段执行命令、rootless 用户命名空间重执行——都可以通过库 API 以编程方式驱动。把 Buildah 集成进自己的构建工具意味着你可以获得完整的镜像构建语义支持 Dockerfile/Containerfile 解析、多阶段构建等能力不必自己重写镜像层逻辑rootless 支持普通用户即可构建镜像无需系统管理员权限可编程的构建步骤通过Builder上的方法按需添加文件、执行命令、设置配置并最终提交镜像。本教程的示例将构建一个包含 Node.js 和入口脚本script.js的镜像全程只用库 API不调用任何 Buildah 可执行文件。引导项目并安装开发依赖准备 Buildah 本身的构建环境由于要在自己的 Go 程序中 import Buildah 库首先需要完成 Buildah 自身的开发依赖安装。按照 install.md 中 Building from scratch 一节的说明引导构建环境并特别关注其中 Installation from GitHub 一节创建一个用于存放 Buildah 项目的目录并完成源码获取。初始化你的 Go 项目假设你已经位于自己项目的目录中运行以下命令初始化 Go modulesgo mod init安装必需的开发包Buildah 依赖多个底层系统库编译时需要有对应的开发头文件。以 Fedora/RHEL 系为例dnf install btrfs-progs-devel gpgme-devel passt各发行版包名略有差异openSUSEzypper install libbtrfs-devel libgpgme-devel passtDebian / Ubuntuapt install libbtrfs-dev libgpgme-dev passt其中btrfs-progs-devellibbtrfs提供 Btrfs 存储驱动的开发头文件gpgme-devel提供镜像签名验证所需的 GPG 支持passt是 rootless 模式下网络助手pasta的依赖。缺少这些包时go get拉取依赖或最终编译会因找不到 CGO 依赖而失败。将 Buildah 引入依赖go get go.podman.io/buildahgo get会同时拉取go.podman.io/storage容器存储层、go.podman.io/image镜像管理和go.podman.io/common公共配置等传递依赖。在当前仓库的 go.mod 中可以看到这些模块正是 Buildah 库的顶层依赖。核心概念storage.Store与buildah.Builder在动手写代码之前先理解两个核心抽象storage.Store容器存储层提供的存储接口定义于go.podman.io/storage包负责管理本地镜像与容器的持久化。构建过程中的中间层和最终镜像都会落到这个存储中。buildah.Builder一个正在构建中的容器的抽象。它在某个存储之上创建提供一系列方法用来配置构建如SetCmd、SetEnv、定义构建步骤如Add、Run以及最终提交镜像Commit。在仓库源码中BuilderOptions结构体定义于 buildah.go它集中描述了初始化 Builder 时需要的全部配置而NewBuilder函数见 buildah.go是创建构建容器的入口。下面我们逐一走通整个流程。第一步初始化存储后端要实例化Builder首先需要拿到一个storage.Store。最直接的方式是使用默认存储选项buildStoreOptions, err : storage.DefaultStoreOptions() buildStore, err : storage.GetStore(buildStoreOptions)storage.DefaultStoreOptions()返回当前系统下的默认存储配置包括存储根目录rootless 下是~/.local/share/containers/storageroot 下是/var/lib/containers/storage、驱动类型等storage.GetStore(options)依据这些选项打开必要时创建存储返回的buildStore将承载构建容器与镜像数据。示例的完整代码中还会在程序退出前调用defer buildStore.Shutdown(false)优雅地关闭存储并释放锁与资源。第二步配置并实例化 Builder定义构建选项指定基础镜像builderOpts : buildah.BuilderOptions{ FromImage: docker.io/library/node:12-alpine, // base image }FromImage是构建的起点镜像名称可以是任意可解析的镜像引用也可以留空或填scratch表示不基于任何镜像从零开始构建这一语义在 buildah.go 的注释中有明确说明。BuilderOptions中还有其他常用字段可以按需配置字段作用FromImage基础镜像名称空值或scratch表示从零构建Args构建期可传入的变量类似--build-argPullPolicy镜像拉取策略PullIfMissing、PullAlways或PullNeverRegistry镜像名无法解析时预置的前缀仓库地址Container构建容器的自定义名称CapabilitiesRUN 阶段命令可用的 capability 列表IsolationRUN 阶段的隔离方式OCI / chroot 等ConfigureNetwork是否在新建网络命名空间中配置网络Format最终提交镜像的格式OCI / DockerCommonBuildOpts与buildah build命令行共享的通用构建选项实例化 Builderbuilder, err : buildah.NewBuilder(context.TODO(), buildStore, builderOpts)从源码看NewBuilder 会在CommonBuildOpts为 nil 时自动补一个空值再调用内部实现newBuilder。它会基于FromImage拉取/复用基础镜像并创建对应的构建容器。第三步添加文件与配置入口命令把本地文件放进容器使用Add方法把本地的script.js复制进容器的/home/node/目录err builder.Add(/home/node/, false, buildah.AddAndCopyOptions{}, script.js)Add的原型为Add(destination string, extract bool, options AddAndCopyOptions, sources ...string) error见 add.go它会把sources指定的本地文件或目录复制到容器根文件系统的destination路径下第二个参数extract为true时若源文件是归档tar 等会将其内容解包而非作为文件整体复制第三个参数AddAndCopyOptions可携带上下文目录、权限Chown/Chmod、Excludes等额外选项本例传空结构体即可内部实现会先挂载容器文件系统b.Mount完成复制后再卸载因此调用方无需关心挂载细节。设置容器启动命令builder.SetCmd([]string{node, /home/node/script.js})SetCmd见 config.go写入 OCI 配置中的Cmd字段也就是镜像被运行时默认执行的命令。除了SetCmdBuilder还提供SetEnv、SetEntrypoint、SetWorkingDir、SetUser等一批配置方法与buildah config子命令的能力一一对应。第四步为 Run() 准备默认值如果你的构建过程需要在容器内执行命令等价于 Dockerfile 中的RUN那么需要补充几个默认值它们不会被自动拾取conf, err : config.Default() capabilitiesForRoot, err : conf.Capabilities(root, nil, nil) isolation, err : parse.IsolationOption()这里有三层含义config.Default()返回全局容器/构建配置它决定默认的 capability 集合、网络与隔离策略等conf.Capabilities(root, nil, nil)取出以 root 用户运行命令时默认授予的 capability 列表后续可放进BuilderOptions.Capabilities确保 RUN 阶段拥有合理的权限例如执行date这类命令不需要额外提权但某些操作如挂载、网络配置则需要parse.IsolationOption()解析隔离模式。传入空字符串时返回平台默认值也可以显式传入oci、rootless、chroot或default覆盖。对应实现见 pkg/parse/parse.go未知值会报unrecognized isolation type错误。之后在调用Run时把 isolation 显式传进去err builder.Run([]string{sh, -c, date /home/node/build-date.txt}, buildah.RunOptions{Isolation: isolation, Terminal: buildah.WithoutTerminal})RunOptions见 run.go还支持User、Env、WorkingDir、Hostname、Mounts、ConfigureNetwork、Terminal等字段。Terminal决定命令是否在伪终端中执行默认在 stdout 连接终端时才使用终端也可以用WithTerminal/WithoutTerminal强制指定库调用场景下一般用WithoutTerminal避免日志被终端控制序列污染。Run只是RunContext(ctx, ...)的便捷封装见 run.go需要取消传播时可以直接调用RunContext。第五步提交镜像构建内容就绪后先创建镜像引用imageRef, err : is.Transport.ParseStoreReference(buildStore, docker.io/myusername/my-image)ParseStoreReference把形如docker.io/myusername/my-image的字符串解析为指向本地存储中目标镜像的引用is是go.podman.io/image/v5/storage包的别名。然后提交imageId, _, _, err : builder.Commit(context.TODO(), imageRef, buildah.CommitOptions{})Commit见 commit.go把构建容器的根文件系统差异打包成新层、合并配置并写入存储返回四个值镜像 ID、规范引用canonical reference和镜像摘要digest。CommitOptions中可以配置字段作用PreferredManifestType首选清单类型OCI / DockerCompression/CompressionFormat层压缩算法默认不压缩推荐archive.GzipAdditionalTags为镜像附加的额外标签Squash将所有层合并为单层OmitHistory不向镜像配置写入构建历史IIDFile将镜像 IDsha256:前缀写入指定文件SystemContext携带凭证等认证信息提交完成后你的自定义构建工具就拥有了一张完整可用的 OCI 镜像。开启 Rootless 模式要让构建工具支持普通用户非 root构建需要引入用户命名空间重执行机制。导入go.podman.io/storage/pkg/unshare并在main()开头加入if buildah.InitReexec() { return } unshare.MaybeReexecUsingUserNamespace(false)这段代码的作用是让应用程序在用户命名空间内重新执行自己并在其中获得 root 权限。其原理是——buildah.InitReexec()是对reexec.Init()的封装见 util.go它注册了内部命令处理器并探测是否需要以特殊模式重新执行unshare.MaybeReexecUsingUserNamespace(false)则检查当前进程是否已在用户命名空间中若没有则重新以映射后的 root 身份启动。InitReexec()返回true时表示当前进程本身就是一个重执行出来的辅助进程此时main()应立即return把控制权交还给 reexec 框架。由于 reexec 机制也被 Buildah 内部多项功能如 mount 辅助、chroot 等复用它应该始终被调用而不是仅在 rootless 场景下才需要。加入这两行后即使以普通用户身份运行你的构建工具也可以完成镜像的拉取、构建与提交。完整代码把上述所有环节组装起来得到一个可在本地运行的完整 CLI 构建工具假设目录下已有script.jspackage main import ( context fmt go.podman.io/buildah go.podman.io/buildah/pkg/parse go.podman.io/common/pkg/config is go.podman.io/image/v5/storage go.podman.io/storage go.podman.io/storage/pkg/unshare ) func main() { if buildah.InitReexec() { return } unshare.MaybeReexecUsingUserNamespace(false) buildStoreOptions, err : storage.DefaultStoreOptions() if err ! nil { panic(err) } conf, err : config.Default() if err ! nil { panic(err) } capabilitiesForRoot, err : conf.Capabilities(root, nil, nil) if err ! nil { panic(err) } buildStore, err : storage.GetStore(buildStoreOptions) if err ! nil { panic(err) } defer buildStore.Shutdown(false) builderOpts : buildah.BuilderOptions{ FromImage: docker.io/library/node:12-alpine, Capabilities: capabilitiesForRoot, } builder, err : buildah.NewBuilder(context.TODO(), buildStore, builderOpts) if err ! nil { panic(err) } defer builder.Delete() err builder.Add(/home/node/, false, buildah.AddAndCopyOptions{}, script.js) if err ! nil { panic(err) } isolation, err : parse.IsolationOption() if err ! nil { panic(err) } err builder.Run([]string{sh, -c, date /home/node/build-date.txt}, buildah.RunOptions{Isolation: isolation, Terminal: buildah.WithoutTerminal}) if err ! nil { panic(err) } builder.SetCmd([]string{node, /home/node/script.js}) imageRef, err : is.Transport.ParseStoreReference(buildStore, docker.io/myusername/my-image) if err ! nil { panic(err) } imageId, _, _, err : builder.Commit(context.TODO(), imageRef, buildah.CommitOptions{}) if err ! nil { panic(err) } fmt.Printf(Image built! %s\n, imageId) }几点使用说明defer builder.Delete()在程序退出时清理构建容器避免在存储中留下中间容器defer buildStore.Shutdown(false)关闭存储参数表示是否强制关闭false为正常关闭panic(err)仅适合教程示例的简单错误处理生产代码建议使用更健壮的错误返回与日志记录镜像提交后打印的imageId形如sha256:...可用buildah images或podman images等工具在本地存储中查看。进一步探索想要基于 Dockerfile 而不是手写构建步骤Builder与imagebuildah模块见 imagebuildah/executor.go配合可实现完整的 Dockerfile 解析与执行更多配置方法SetEnv、SetEntrypoint、SetUser等见 config.go与buildah config子命令一一对应BuilderInfo结构见 buildah.go可用于在构建前后检查构建容器的配置状态仓库中的测试文件如 buildah_test.go、commit_test.go展示了库 API 在真实场景下的用法可作为编写自己构建工具的参考。赞分享云原生【免费下载链接】buildahA tool that facilitates building OCI images.项目地址https://gitcode.com/gh_mirrors/bu/buildah点击查看免费下载相关推荐Buildah项目教程将Buildah集成到你的构建工具中Buildah项目教程将Buildah集成到你的构建工具中 前言 Buildah是一个强大的容器镜像构建工具它不仅可以作为独立命令行工具使用还可以作为Go云原生Buildah: OCI镜像构建工具Buildah: OCI镜像构建工具 1. 项目介绍 Buildah是一个开源命令行工具用于构建Open Container Initiative OCI 容云原生如何将Buildah集成到自定义构建工具中完整指南如何将Buildah集成到自定义构建工具中完整指南 Buildah是一个强大的OCI镜像构建工具它允许开发者以编程方式创建和管理容器镜像。本文将详细介绍如何云原生上一篇原神祈愿数据分析神器让抽卡记录一目了然下一篇Chatbox AI助手终极探索从零到精通的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
