首页/新闻资讯/正文详情

Buildah 入门实战:从 scratch 到 Dockerfile,构建可移植 OCI 镜像的完整工作流

发布时间:2026/9/25 17:54:03 来源:云帆数科 栏目:资讯中心
Buildah 入门实战:从 scratch 到 Dockerfile,构建可移植 OCI 镜像的完整工作流
云原生【免费下载链接】buildahA tool that facilitates building OCI images.项目地址https://gitcode.com/gh_mirrors/bu/buildah点击查看免费下载本文基于 Buildah 官方入门教程docs/tutorials/01-intro.md整理并深入扩展带你完整走一遍 Buildah 构建 OCI 容器镜像的核心工作流安装与验证、基于现有镜像创建 working container、从scratch空镜像逐层填充内容、提交与配置元数据以及使用 Dockerfile/Containerfile 构建镜像。读完之后你将掌握 Buildah CLI 的典型操作序列并理解每个命令背后对应的源码实现与底层库containers/image、containers/storage的协作关系。一、Buildah 与 OCI 镜像规范Buildah 的目标是构建符合 OCI 镜像规范 的容器镜像。镜像既可以基于现有镜像扩展也可以完全从空白scratch开始还可以直接由 Dockerfile 驱动构建。Buildah 的镜像能力建立在两个基础库之上containers/image提供镜像的复制push、pull、检视inspect与签名sign机制containers/storage提供文件系统层layers、容器镜像以及容器本身的存储机制。Buildah 本身是一个 CLI它利用上述两个库来构建、移动和管理容器镜像与工作容器。由于产物严格遵循 OCI 标准用 Buildah 构建的镜像可以在 Docker 等其他容器环境中运行。需要明确的适用边界Buildah 支持多种 Linux 发行版但不支持 Windows 或 macOSBuildah 专注于构建OCI 镜像而 Podman 提供覆盖面更广的命令集维护、修改、运行镜像与容器。二者同属 containers 生态定位互补。二、安装 Buildah官方入门教程以使用dnf包管理器的 Linux 发行版为前提安装步骤如下安装包需要 root 权限$ sudo -s # dnf -y install buildah仓库中的 install.md 给出了更多发行版的安装方式包括Debian/Ubuntusudo apt-get -y install buildahFedorasudo dnf -y install buildahCentOSsudo yum -y install buildahopenSUSEsudo zypper install buildahArch Linuxsudo pacman -S buildahGentoosudo emerge app-containers/buildah。除了发行版差异还有两个关键前提值得注意内核要求RHEL/CentOS 上要求 7.4 及以上内核其他发行版需要支持 OverlayFS 或 fuse-overlayfs 的内核runc 依赖buildah run执行命令、或buildah build遇到RUN指令时Buildah 依赖runc来真正运行进程。通过 yum/dnf/apt 安装 Buildah 时通常会顺带装好 runc。Rootless免 root运行如果计划以非 root 用户rootless user运行 Buildah系统管理员可能需要预先做额外配置。Buildah 对 rootless 用户的配置要求与 Podman 完全一致可参考 Podman 官方的 rootless tutorial。仓库中的 buildah-unshare.1.md 则说明了后文会用到的buildah unshare命令它用于创建并进入 user namespace 与 mount namespace。三、安装后验证images、containers 与 working container安装完成后先确认本地存储是空的。buildah images列出所有镜像buildah containers列出所有 working container# buildah images # buildah containers此时两条命令都应该没有输出。接下来创建第一个 working container# container$(buildah from fedora)这里有两点值得深入理解。第一buildah from的输出可以直接赋给 shell 变量。从源码看cmd/buildah/from.go 中fromCmd在成功构建Builder之后执行fmt.Printf(%s\n, builder.Container)把容器名打印到标准输出——这正是教程中container$(buildah from fedora)能够捕获名称的机制。第二working container 的命名规则。Buildah 默认会在基础镜像名后追加-working-container后缀来生成容器名例如fedora-working-container。命名逻辑位于 new.goname : working-container if options.ContainerSuffix ! { name options.ContainerSuffix } if options.Container ! { name options.Container } else { if imageSpec ! { name imageNamePrefix(imageSpec) - name } }其中imageNamePrefixnew.go会去掉镜像名中的 tag、digest截断到 12 位、与/部分只保留最后一段镜像名从而得到fedora这样的前缀。如果同名容器已存在findUnusedContainer会进一步追加编号避免冲突。查看变量内容并进入容器执行命令# echo $container fedora-working-container # buildah run $container bash执行后会看到一个新的 shell 提示符说明 bash 正在容器内运行。注意buildah run的定位主要用于调试和构建过程中的命令执行。如果要在生产环境长期运行容器更适合使用 Podman 或 CRI-O 这类完整的容器运行时。buildah run中的--分隔符退出容器后教程演示了容器内缺软件再装软件的场景# buildah run $container java容器里没装 Java会看到类似这样的报错runc create failed: unable to start start container process: exec: java: executable file not found in $PATH于是需要在容器里安装 Java# buildah run $container -- dnf -y install java这里的--语法告诉 Buildah其后不再解析buildah run自身的选项--之后的所有内容都作为容器内命令的参数。当你要执行的容器内命令自身携带选项如dnf -y install时使用--是必要的可以防止选项被 Buildah 误吞。之后再次运行buildah run $container java将输出 Java 的标准Usage信息说明安装成功。四、从 scratch 构建真正从零的镜像Buildah 的一个重要能力是从空白构建镜像可以精确控制镜像内容剔除生产环境不需要的组件比如大多数生产镜像并不需要dnf这样的包管理器。4.1 创建空容器特殊的镜像名scratch告诉 Buildah 创建一个空容器——它只带有少量元数据没有任何实际的 Linux 内容# newcontainer$(buildah from scratch) # buildah containers输出类似CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME 82af3b9a9488 * 3d85fcda5754 docker.io/library/fedora:latest fedora-working-container ac8fa6be0f0a * scratch working-container注意两点空容器的默认名字就是working-container对应 new.go 中的默认值没有镜像名可作前缀运行buildah images时看不到名为scratch的镜像——scratch只是一个特殊值表示该 working container 并非基于任何镜像从 nothing 开始。此时在容器里执行buildah run $newcontainer bash会失败——容器里连 bash、dnf 都没有它本质上只是内核之上的一层空文件系统。4.2 用 buildah mount 暴露容器根文件系统要把内容塞进这个空容器需要buildah mount命令# scratchmnt$(buildah mount $newcontainer) # echo $scratchmnt /var/lib/containers/storage/overlay/b78d0e11957d15b5d1fe776293bd40a36c28825fb6cf76f407b4d0a95b2a200d/merged输出的路径是一个overlay 挂载点它就是容器使用的根文件系统。以 root 运行时overlay 挂载点位于/var/lib/containers/storage之下rootless 模式下则位于家目录的.local/share/containers/storage之下——这正体现了底层 containers/storage 库的存储布局。从源码看buildah mount最终调用 mount.go 中的Builder.Mountfunc (b *Builder) Mount(label string) (string, error) { mountpoint, err : b.store.Mount(b.ContainerID, label) if err ! nil { return , fmt.Errorf(mounting build container %q: %w, b.ContainerID, err) } b.MountPoint mountpoint err b.Save() if err ! nil { return , fmt.Errorf(saving updated state for build container %q: %w, b.ContainerID, err) } return mountpoint, nil }可以看到它委托给存储驱动b.store.Mount完成实际的 overlay 挂载并把挂载点持久化到 Builder 状态b.Save()供后续buildah unmount时清理。rootless 注意事项rootless 模式下直接执行buildah mount会失败因为挂载容器必须在你自己拥有的 mount namespace 中进行。正确的做法是先用buildah unshare创建并进入 user namespace 与 mount namespace再执行 mount并且由于 shell 环境变了需要把变量导出$ export newcontainer $ buildah unshare # scratchmnt$(buildah mount $newcontainer)4.3 用 dnf installroot 向容器填充软件拿到挂载点之后就可以在宿主机上直接装包进容器。教程以安装bash与coreutils为例换成nginx等任何需要的包也一样# dnf install --installroot $scratchmnt --releasever 42 bash coreutils --use-host-config --setopt *.countmefalse --setopt installweak_depsfalse -y关键参数是--installroot $scratchmnt让 dnf 把包装进挂载目录而不是宿主机。教程特别提示示例中的--releasever 42对应 Fedora 42这个版本值必须对宿主机上的 dnf 有效——例如在 RHEL 平台上应写--releasever 8.1之类的有效版本。若希望容器最终基于某个特定发行版可把buildah from scratch换成buildah from fedora并使用该平台的版本值。验证一下容器内确实有了/usr/bin# buildah run $newcontainer sh sh-5.1# cd /usr/bin sh-5.1# ls sh-5.1# exit4.4 copy、config、commit完成第一张镜像在宿主机上创建一个可执行脚本runecho.sh#!/usr/bin/env bash for i in seq 0 9; do echo This is a new container from ipbabble [ $i ] done# chmod x runecho.sh然后三步完成镜像# buildah copy $newcontainer ./runecho.sh /usr/bin/ # buildah config --cmd /usr/bin/runecho.sh $newcontainer # buildah commit $newcontainer newimage这一步值得理解buildah run与podman run的本质区别教程给出的类比非常准确buildah run等价于 Dockerfile 中的RUN它永远需要你显式告诉它要运行什么命令podman run等价于docker run它可以读取镜像配置即上一步buildah config --cmd写入的默认命令来决定运行什么。先用 Buildah 直接指定命令验证脚本可执行# buildah run $newcontainer /usr/bin/runecho.sh This is a new container from ipbabble [ 0 ] This is a new container from ipbabble [ 1 ] ... This is a new container from ipbabble [ 9 ]再用 Podman 基于新镜像起一个全新容器不指定命令它会自动执行镜像配置里的--cmd# dnf -y install podman # 先安装 # podman run --rm newimage This is a new container from ipbabble [ 0 ] ... This is a new container from ipbabble [ 9 ]输出一致说明这个从 scratch 构建的镜像完全可用。4.5 元数据、二次 commit 与清理继续为工作容器补充元数据# buildah config --created-by ipbabble $newcontainer # buildah config --author wgh at redhat.com ipbabble --label namefedora42-bashecho $newcontainer # buildah inspect $newcontainer注意一个容易踩的坑元数据修改发生在上一次 commit 之后所以必须再次 commit 才能得到包含新元数据的镜像# buildah unmount $newcontainer # buildah commit $newcontainer fedora-bashecho # buildah images此时会看到新镜像localhost/fedora-bashecho:latest。检查镜像元数据用--typeimage# buildah inspect --typeimage fedora-bashecho之后每次需要基于该镜像起容器直接buildah from fedora-bashecho即可。工作容器已完成使命可以删除按变量或按名字等价# buildah rm $newcontainer # buildah rm working-container五、可移植性把镜像推给 Docker daemon教程用一个实验证明 Buildah 产出的 OCI 镜像是标准、可移植的安装并启动 Docker然后把镜像从 containers/storage 的存储区复制到 Docker daemon 的存储区/var/lib/docker# dnf -y install docker # systemctl start docker # buildah push fedora-bashecho docker-daemon:fedora-bashecho:latest # docker run --rm fedora-bashecho This is a new container from ipbabble [ 0 ] ... This is a new container from ipbabble [ 9 ]几个要点docker-daemon:是显式的 transport 前缀。docker://默认指向 Registry HTTP API V2、docker-daemon:指向本地 Docker daemon 的内部存储、dir:、oci:、oci-archive:、docker-archive:等 transport 的完整定义见 buildah-from.1.md 与 buildah-push.1.md底层机制containers/image 库调用 containers/storage 库从 Buildah 的存储位置读出镜像内容发送给本地 Docker daemon 写入其存储。教程提醒这一步通常用不到——用 Buildah 的人多半不用 Docker这里仅作可移植性演示架构差异Docker 必须依赖一个常驻 daemon 进程才能执行任何客户端命令Buildah 与 Podman 则没有 daemon 依赖命令直接操作存储与命名空间。演示完成后可以dnf -y remove docker收尾。六、使用 Containerfile/Dockerfile 构建镜像如果你已有现成的 Dockerfile 资产Buildah 可以无缝复用build命令接受 Dockerfile 作为输入产出 OCI 镜像。教程给出的示例 Dockerfile 如下# Base on the most recently released Fedora FROM fedora:latest MAINTAINER ipbabble email buildahboyredhat.com # not a real email # Install updates and httpd RUN echo Updating all fedora packages; dnf -y update; dnf -y clean all RUN echo Installing httpd; dnf -y install httpd dnf -y clean all # Expose the default httpd port 80 EXPOSE 80 # Run the httpd CMD [/usr/sbin/httpd, -DFOREGROUND]执行构建# buildah build -f Dockerfile -t fedora-httpd .由于buildah build默认使用当前目录下的Dockerfile并以当前目录作为构建上下文上式可以简写为# buildah build -t fedora-httpd构建过程中你会看到 Dockerfile 的每一步依次执行FROM会先创建一个以镜像名-working-container命名的工作容器RUN指令经由 runc 在容器内执行——这与前面buildah run的机制同源完成后buildah images中出现新镜像。用 Podman 起容器验证服务并做端口映射# podman run --rm -p 8123:80 fedora-httpd另开一个 shell# curl localhost:8123看到标准的 Apache 欢迎页即验证成功。教程最后的开放练习修改 Dockerfile不安装 httpd改用ADD指令引入前面的runecho.sh并把它设为CMD再走一遍构建流程。仓库的 tests/ 目录中有大量围绕 Dockerfile 行为的集成测试如 tests/bud.bats 及各tests/bud/子目录的测试用例可以结合源码进一步理解buildah build对COPY、ADD、多阶段构建、ARG/ENV等指令的具体处理逻辑。七、小结一条完整的 Buildah 心智模型把上面的操作串起来Buildah 的核心工作模型是四步buildah from image|scratch创建 working container源码入口 cmd/buildah/from.go命名规则见 new.go填充内容buildah run在容器内执行命令、buildah copy拷入文件、buildah mount 宿主工具直接操作根文件系统实现见 mount.gobuildah config写入元数据cmd、label、author 等buildah commit把工作容器的变更固化为 OCI 镜像之后可通过buildah push发送到 registry、Docker daemon 等任意 transport。所有产物严格遵循 OCI 规范因此天然可移植。若想继续深入建议按序阅读 docs/tutorials/ 下的后续教程镜像仓库交互、ONBUILD 机制、把 Buildah 作为库集成进自有构建工具、rootless OpenShift 构建以及各命令的 man pagedocs/buildah-run.1.md、docs/buildah-commit.1.md、docs/buildah-mount.1.md、docs/buildah-config.1.md、docs/buildah-push.1.md 等它们覆盖了本教程未展开的全部命令行参数。赞分享云原生【免费下载链接】buildahA tool that facilitates building OCI images.项目地址https://gitcode.com/gh_mirrors/bu/buildah点击查看免费下载相关推荐container构建系统详解从Dockerfile到OCI镜像的完整流程container构建系统详解从Dockerfile到OCI镜像的完整流程 container构建系统是专门为Mac平台优化的Linux容器构建工具采用SwCLI虚拟化容器运行时云原生Buildah: OCI镜像构建工具Buildah: OCI镜像构建工具 1. 项目介绍 Buildah是一个开源命令行工具用于构建Open Container Initiative OCI 容云原生终极指南Docker构建工具链如何从Dockerfile到OCI镜像的完整流程终极指南Docker构建工具链如何从Dockerfile到OCI镜像的完整流程 Docker构建工具链是现代容器化开发的核心它通过Dockerfile指令逐云原生容器运行时虚拟化容器编排上一篇Apache Pulsar 授权机制详解Authorization 配置、Superusers 与 Proxy Roles 实战指南下一篇Lynx 模板二进制编码中的 Style Object 解析与编码实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Atlas 300V 24G推理卡如何高效部署YOLO目标检测
Atlas 300V 24G推理卡如何高效部署YOLO目标检测

1. Atlas 300V 24G的真实定位:它是一张推理卡,不是训练卡最近在群里看到好几个朋友在问同一个问题:“Atlas 300V 24G是运算加速卡吗?”还有人直接拿它对标GPU跑训练,问能不能用来部署YOLO。这个问题其实问到了很多刚接… · 2026/9/25 17:54:03

Atlas 300V实战:CANN部署与YOLO推理全流程
Atlas 300V实战:CANN部署与YOLO推理全流程

1. 拿到Atlas 300V,先搞清楚它到底是一张什么卡如果你最近在搞边缘AI或者服务器端推理,国内市场的视野里大概绕不开昇腾系的产品。我第一次拿到Atlas 300V 24G的时候,心里其实是有个问号的——这玩意儿到底算不算一张“运算加速卡”&#xff… · 2026/9/25 17:53:57

Spark without Hive:轻量级生产环境构建指南
Spark without Hive:轻量级生产环境构建指南

简介:本资源是专为大数据工程师与 Spark 高级使用者设计的 Spark 2.3.0 精简发行版,面向需在 Hadoop 2.x 环境中实现 Hive on Spark 但规避 Hive JAR 冗余依赖的场景,解决 Spark 与 Hive 元数据层解耦集成的实际部署难题。压缩包共867个文件&… · 2026/9/25 17:53:51

小模型能当裁判吗?一场关于强化学习奖励成本的实验
小模型能当裁判吗?一场关于强化学习奖励成本的实验

先问你一个问题。如果你要训练一个AI模型写深度研究报告,怎么判断它写得好不好?数学题有标准答案,代码题能跑测试用例,可一篇论文该不该给9分还是7分,谁说了算?过去几年,大模型圈子里流行的做法… · 2026/9/25 18:25:27

数据闭环分层抽帧策略从 TB 级采集数据中提取高价值帧:三道成本闸门
数据闭环分层抽帧策略从 TB 级采集数据中提取高价值帧:三道成本闸门

上一篇讲完了挖掘平台的架构骨架,从这篇开始填血肉。平台拿到采集数据后做的第一件事是「抽帧」——把视频形态的 clip 变成一张张图片。为什么必须做这一步?因为下游所有能力都是「认图不认视频」的:VLM 推理要喂图片,Embedding … · 2026/9/25 18:25:27

Atlas 300V 24G推理卡实战:从CANN环境搭建到YOLOv5模型部署全流程
Atlas 300V 24G推理卡实战:从CANN环境搭建到YOLOv5模型部署全流程

先给结论:Atlas 300V 24G确实是一张“运算加速卡”,但你要是拿它当普通图形卡用,就完全理解偏了。它是一张面向AI推理场景的加速卡,最近“atlas部署yolo”这么热,主要还是因为这卡性价比够看、国产化适配到位&#xff… · 2026/9/25 18:25:27

把已经跑过的智能体聊天记录,重新变成能用的编程练习场
把已经跑过的智能体聊天记录,重新变成能用的编程练习场

2014 年,语音识别领域有一件让所有人挠头的事:训练一个能听懂人说话的模型,需要成千上万小时的标注音频。可标注音频这东西,贵、慢、还容易出错。十年后,AI 编程智能体(就是那种能在命令行里帮你写代码、修… · 2026/9/25 18:25:27

DM0.5连续霸榜各大评测,具身预训练的价值正在显现
DM0.5连续霸榜各大评测,具身预训练的价值正在显现

具身智能的榜单越来越多,模型成绩也在不断刷新。 相比于看谁拿第一,另一个问题更值得关注:这些榜单,究竟在向机器人提出什么要求? 同样是抓起一个物体,但完成抓取只是第一层。如果指令指定了颜色、大小&a… · 2026/9/25 18:25:21

不用协方差矩阵也能算风险?AI读财经新闻给出的一份“风险担保书“
不用协方差矩阵也能算风险?AI读财经新闻给出的一份“风险担保书“

你有没有想过一个问题:一个基金经理想要分散风险,把钱分散投资到52只不同的股票上,理论上他需要知道的是什么?不是每只股票自己涨跌多少,而是它们**一起**涨跌的规律。用金融行话说,这叫协方差矩阵。可这东… · 2026/9/25 18:25:21

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码