- 云原生
【免费下载链接】buildah
A tool that facilitates building OCI images.
本篇技术指南聚焦 Buildah 的buildah containers命令(别名list、ls、ps),它用于列出当前存储中处于"工作状态"的 Buildah 构建容器、它们的名称与 ID,以及初始化它们所依据的基础镜像的名称与 ID。读完本文,你将掌握该命令的全部选项(--all、--filter、--format、--json、--noheading、--notruncate、--quiet)的用法、输出格式与匹配规则,并能结合源码理解其实现原理,从而在日常镜像构建、容器管理中高效地查询工作容器状态。
命令概述
buildah containers是一个用于**列出 Buildah 工作容器(working container)**及其基础镜像的命令。工作容器是执行buildah from或buildah bud(即buildah build)时创建的临时容器,镜像构建过程中所有文件变更都发生在其中,最终通过buildah commit提交为新镜像。
命令的正式用法(参见 SYNOPSIS):
buildah containers [options]该命令不接受位置参数。从 cmd/buildah/containers.go 的源码可以看到,若传入多余参数会直接报错:
if len(args) > 0 { return errors.New("'buildah containers' does not accept arguments") }命令注册时定义了三个别名,习惯 Docker/Podman 的用户可以无缝迁移:
Use: "containers", Aliases: []string{"list", "ls", "ps"},因此buildah ps、buildah ls、buildah list与buildah containers完全等价。
默认输出解读
不带任何选项执行:
buildah containers默认输出为表格形式,每行对应一个由 Buildah 创建的工作容器:
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME ccf84de04b80 * 53ce4390f2ad registry.access.redhat.com/ub... ubi8-working-container 45be1d806fc5 * 16ea53ea7c65 docker.io/library/busybox:latest busybox-working-container各列含义:
| 列 | 含义 |
|---|---|
| CONTAINER ID | 容器的短 ID(默认截断为 12 位) |
| BUILDER | 标记该容器是否由 Buildah 创建;*表示是 Buildah 工作容器 |
| IMAGE ID | 基础镜像的短 ID |
| IMAGE NAME | 基础镜像的名称(默认超过 32 字符会被截断并以...结尾) |
| CONTAINER NAME | 容器名称,默认命名模式为<镜像名>-working-container |
默认情况下,ID 被截断为 12 位、镜像名截断为 32 字符。对应源码位于 containerOutputUsingFormatString:
// 截断模式 fmt.Printf("%-12.12s %-8s %-12.12s %-32s %s\n", params.ContainerID, params.Builder, params.ImageID, util.TruncateString(params.ImageName, 32), params.ContainerName) // 非截断模式 fmt.Printf("%-64s %-8s %-64s %-32s %s\n", params.ContainerID, params.Builder, params.ImageID, params.ImageName, params.ContainerName)其中镜像名的...截断由 util.TruncateString 实现:超过指定长度(32)时,末尾替换为省略号。
选项详解
--all, -a
列出所有容器,包括那些并非由 Buildah 创建、也未在使用的容器(例如由 Podman 创建的普通容器)。Buildah 创建的容器会在BUILDER列以*标记。
从源码 outputContainers 可以看到实现思路:--all模式下读取存储中全部容器(store.Containers()),并通过builderMap记录 Buildah 工作容器的 ID 集合,以此判定每行是否标记*。
_, ours := builderMap[container.ID] builder := "" if ours { builder = " *" }--filter, -f
按给定条件过滤输出。支持的过滤器如下:
| 过滤器 | 描述 |
|---|---|
id | 容器 ID 前缀匹配 |
name | 容器名称包含匹配(子串匹配) |
ancestor | 镜像名称或镜像 ID,匹配创建容器所用的镜像或其后代 |
过滤器格式为key=value,多个过滤器以逗号分隔。例如:
buildah containers --filter ancestor=ubuntu输出:
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME fbfd3505376e * 0ff04b2e7b63 docker.io/library/ubuntu:latest ubuntu-working-container过滤器解析逻辑在 parseCtrFilter:先按,分割,再按第一个=拆成键值对,未知过滤器键会报错invalid filter %q。三种过滤器的实际匹配规则如下(matchesCtrFilter):
id:使用前缀匹配(strings.HasPrefix,见 matchesID),因此传入容器 ID 的前几位即可;name:使用子串包含匹配(strings.Contains,见 matchesCtrName),无需精确完整名称;ancestor:先尝试镜像 ID 前缀匹配,再尝试镜像名称后缀匹配(见 matchesAncestor)。名称匹配时若参数含:(带 tag),则要求仓库名后缀与 tag 均一致;否则仅匹配仓库名后缀(见 matchesReference)。
--format
使用 Go template 自定义输出格式。支持的占位符:
| 占位符 | 描述 |
|---|---|
.ContainerID | 容器 ID |
.Builder | 该容器是否由 Buildah 创建 |
.ImageID | 镜像 ID |
.ImageName | 镜像名称 |
.ContainerName | 容器名称 |
示例,仅输出容器 ID 与名称:
buildah containers --format "{{.ContainerID}} {{.ContainerName}}"ccf84de04b80c309ce6586997c79a769033dc4129db903c1882bc24a058438b8 ubi8-working-container 45be1d806fc533fcfc2beee77e424d87e5990d3ce9214d6b374677d6630bba07 busybox-working-container也可以混入任意文本:
buildah containers --format "Container ID: {{.ContainerID}}"Container ID: ccf84de04b80c309ce6586997c79a769033dc4129db903c1882bc24a058438b8 Container ID: 45be1d806fc533fcfc2beee77e424d87e5990d3ce9214d6b374677d6630bba07实现上,--format通过formats.StdoutTemplateArray结合 containersHeader 定义的列头映射渲染输出(outputContainers)。
注意:--quiet与--format互斥,同时指定会直接报错:
if c.Flag("quiet").Changed && c.Flag("format").Changed { return errors.New("quiet and format are mutually exclusive") }--json
以 JSON 数组格式输出,便于脚本解析。示例如下(文档原样示例):
buildah containers --json[ { "id": "ccf84de04b80c309ce6586997c79a769033dc4129db903c1882bc24a058438b8", "builder": true, "imageid": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", "imagename": "registry.access.redhat.com/ubi8:latest", "containername": "ubi8-working-container" }, { "id": "45be1d806fc533fcfc2beee77e424d87e5990d3ce9214d6b374677d6630bba07", "builder": true, "imageid": "16ea53ea7c652456803632d67517b78a4f9075a10bfdc4fc6b7b4cbf2bc98497", "imagename": "docker.io/library/busybox:latest", "containername": "busybox-working-container" } ]JSON 字段结构与源码中的 jsonContainer 结构体一一对应:id、builder(布尔值)、imageid、imagename、containername,由json.MarshalIndent(..., "", " ")生成带缩进的可读输出。
--noheading, -n
省略表格的列标题行,只输出数据行,便于与其它工具组合做纯数据流处理。
--notruncate
不截断 ID 与镜像名称,输出完整 64 位十六进制 ID 与完整镜像引用。结合 containerOutputHeader 可看到截断/非截断两种表头布局(12 位 vs 64 位列宽)。
--quiet, -q
只输出容器 ID,每行一个,适合直接传递给其它命令(如buildah rm)使用:
buildah containers --quietccf84de04b80c309ce6586997c79a769033dc4129db903c1882bc24a058438b8 45be1d806fc533fcfc2beee77e424d87e5990d3ce9214d6b374677d6630bba07注意--quiet模式下输出的是完整 64 位 ID(outputContainers 中使用%-64s格式化),保证 ID 唯一性,可直接用于buildah rm <id>。
选项组合实战
各选项可自由组合。例如只取不带头部的完整 ID 列表:
buildah containers -q --noheading --notruncateccf84de04b80c309ce6586997c79a769033dc4129db903c1882bc24a058438b8 45be1d806fc533fcfc2beee77e424d87e5990d3ce9214d6b374677d6630bba07再如按名称过滤并自定义输出:
buildah containers --filter name=ubi8 --format "{{.ContainerName}} ({{.ImageName}})"源码级实现剖析
工作容器从哪来
buildah containers(不含--all)只列出 Buildah 自己的工作容器,数据来源是 OpenAllBuilders:
- 调用
store.Containers()读取本地容器存储中的所有容器; - 对每个容器,读取其数据目录中的状态文件(
stateFile)并反序列化为Builder; - 仅当状态文件可解析且容器类型为 Buildah 容器(
b.Type == containerType)时才纳入列表;其他容器被跳过(logrus.Debugf(...)记录后continue)。
因此,"Buildah 工作容器"的判定依据是该容器数据目录下存在 Buildah 写入的状态文件,而非名称前缀等外部特征。
scratch 基础镜像的特殊处理
对于buildah from scratch创建的空工作容器,没有真实基础镜像,其"镜像名"会被展示为scratch。该常量定义于 new.go:
// BaseImageFakeName is the "name" of a source image which we interpret // as "no image". BaseImageFakeName = imagebuilder.NoBaseImageSpecifier在 outputContainers 中,当FromImageID为空时直接返回该占位名:
if id == "" { return buildah.BaseImageFakeName }镜像名的推断
outputContainers维护了一个seenImages缓存:对于容器记录的基础镜像 ID,通过store.Image(id)查询镜像对象并取第一个名称(img.Names[0])作为展示名,避免重复查询(见 imageNameForID)。
测试验证
仓库的 Bats 集成测试 tests/containers.bats 覆盖了该命令的主要行为,可作为实际使用时的行为契约参考:
- 基本列出:创建 alpine 与 busybox 两个工作容器后,
buildah containers输出共 3 行(1 行表头 + 2 行数据); - filter:
buildah containers --filter name=<cid>只输出 2 行(表头 + 1 个匹配容器); - format:
--format "{{.ContainerName}}"输出两行,分别为alpine-working-container与busybox-working-container,印证了默认命名规则; - json:输出内容包含
{,验证 JSON 结构; - noheading:
--noheading输出不包含NAME表头; - quiet:
--quiet每行都是 64 位十六进制 ID(^[0-9a-f]{64}$); - notruncate:
--notruncate输出完整 64 位 ID; - all:在存储中额外用
podman create创建一个非 Buildah 容器后,buildah containers仍输出 2 行,而buildah containers -a输出 3 行——精确验证了--all的行为差异。
典型使用场景
构建现场排查:执行
buildah bud后想确认当前有哪些活跃的工作容器,直接运行buildah containers查看。批量清理:配合
buildah rm一键删除全部工作容器:buildah rm $(buildah containers -q)脚本集成:用
--json或--format输出结构化结果,交由 CI/CD 脚本处理;用-q --noheading --notruncate获取无装饰的完整 ID 列表。区分来源:用
-a查看存储中全部容器,通过BUILDER列的*快速区分 Buildah 工作容器与其它容器(如 Podman 创建的)。
关联阅读
- 命令总览:buildah(1) 手册
- 命令实现源码:cmd/buildah/containers.go
- 工作容器加载逻辑:buildah.go 中 OpenAllBuilders
- 集成测试:tests/containers.bats
- 创建工作容器的基础命令:
buildah from(对应 docs/buildah-from.1.md)与buildah bud(docs/buildah-bud.1)
- 云原生
【免费下载链接】buildah
A tool that facilitates building OCI images.
相关推荐
ModelScope本地化部署方案:构建安全可控的企业级AI推理平台
ModelScope本地化部署方案:构建安全可控的企业级AI推理平台 面对企业敏感数据上云的隐私风险与云端AI服务的不稳定连接,ModelScope本地化部署方
人工智能大模型微调模型评测预训练Buildah容器镜像导入导出性能优化:大型镜像处理
Buildah容器镜像导入导出性能优化:大型镜像处理 在容器化部署流程中,大型镜像的导入导出操作常常成为效率瓶颈。本文将系统介绍Buildah工具在处理GB级镜
云原生Buildah终极指南:容器镜像的tar文件导入导出操作详解
Buildah终极指南:容器镜像的tar文件导入导出操作详解 Buildah 是一款轻量级的容器镜像构建工具,专注于创建符合OCI标准的容器镜像。对于开发者和系
云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考