十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Podman 镜像层级树分析:podman image tree 命令详解与底层实现

Podman 镜像层级树分析:podman image tree 命令详解与底层实现 容器运行时云原生CLI【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址https://gitcode.com/gh_mirrors/po/podman点击查看免费下载导读podman image tree是 Podman 提供的一把镜像解剖刀它把 OCI 镜像内部逐层叠加的存储结构以树形图打印出来让你一眼看清镜像由哪些层组成、每层占用多少存储空间以及各层与本地已有 tag 的对应关系。本文将以此命令的官方手册文档为主体结合当前仓库中 CLI、引擎与 API 三层源码实现完整讲解命令语法、全部选项、真实输出示例以及底层调用链帮助你用它完成镜像体积排查、镜像层级分析等日常运维任务。命令总览podman image tree用于以树形格式打印镜像的层layer层级结构。它归属于podman image命令族其顶层命令定义位于 cmd/podman/images/tree.go手册文档位于 docs/source/markdown/podman-image-tree.1.md。在 tree.go 中可以看到该命令的完整声明treeCmd cobra.Command{ Use: tree [options] IMAGE, Args: cobra.ExactArgs(1), Short: treeDescription, Long: treeDescription, RunE: tree, ValidArgsFunction: common.AutocompleteImages, Example: podman image tree alpine:latest, }几个值得注意的细节命令严格要求恰好一个位置参数cobra.ExactArgs(1)即必须指定一个镜像注册了common.AutocompleteImages作为参数补全函数因此在使用支持补全的 Shell如 bash、zsh、fish参见 completions 目录时输入镜像名可以自动补全该命令是image子命令族的成员通过registry.CliCommand{Command: treeCmd, Parent: imageCmd}挂载所以podman image tree与podman image-tree两种写法均有效。命令语法podman image tree [options] image:tag|image-id位置参数既可以是镜像名:标签如docker.io/library/wordpress也可以是镜像 ID如ae96a4ad4f3f。未指定 tag 时Podman 默认使用latest。功能说明该命令打印的是镜像的层Layer层级结构——即构成该镜像的每一层只读文件系统变更以及它们自底向上的叠加顺序。输出中每一层以ID和Size标注且当某一层恰好对应本地某个已知 tag 的顶层Top Layer时会用Top Layer of: [...]标注出来从而直观地展示这个镜像复用了哪些其他镜像的层。这一语义在 tree.go 的命令描述中定义得很明确Print layer hierarchy of an image in a tree format。层复用的根源在于 OCI/Docker 镜像的分层存储模型多个镜像共享底层时磁盘上只保存一份数据podman image tree正是将这种共享关系可视化。选项说明选项作用--help,-h打印使用说明usage statement--whatrequires显示指定镜像的所有子镜像child images和层--whatrequires 的含义默认不带任何选项时命令从顶层向底层逐层打印展示这个镜像由哪些层构成而加上--whatrequires后输出视角反转以指定镜像为根向下展开所有依赖它的子镜像及它们各自引入的层用于回答谁在用这层、谁继承了这个镜像的问题。该选项在 CLI 层的定义位于 tree.gotreeCmd.Flags().BoolVar(treeOpts.WhatRequires, whatrequires, false, Show all child images and layers of the specified image)对应的选项结构体定义在 pkg/domain/entities/images.go// ImageTreeOptions provides options for ImageEngine.Tree() type ImageTreeOptions struct { WhatRequires bool // Show all child images and layers of the specified image }使用示例示例一查看指定镜像的层结构$ podman image tree docker.io/library/wordpress Image ID: 6e880d17852f Tags: [docker.io/library/wordpress:latest] Size: 429.9MB Image Layers ├── ID: 3c816b4ead84 Size: 58.47MB ├── ID: e39dad2af72e Size: 3.584kB ├── ID: b2d6a702383c Size: 213.6MB ├── ID: 94609408badd Size: 3.584kB ├── ID: f4dddbf86725 Size: 43.04MB ├── ID: 8f695df43a4c Size: 11.78kB ├── ID: c29d67bf8461 Size: 9.728kB ├── ID: 23f4315918f8 Size: 7.68kB ├── ID: d082f93a18b3 Size: 13.51MB ├── ID: 7ea8bedcac69 Size: 4.096kB ├── ID: dc3bbf7b3dc0 Size: 57.53MB ├── ID: fdbbc6404531 Size: 11.78kB ├── ID: 8d24785437c6 Size: 4.608kB ├── ID: 80715f9e8880 Size: 4.608kB Top Layer of: [docker.io/library/php:7.2-apache] ├── ID: c93cbcd6437e Size: 3.573MB ├── ID: dece674f3cd1 Size: 4.608kB ├── ID: 834f4497afda Size: 7.168kB ├── ID: bfe2ce1263f8 Size: 40.06MB └── ID: 748e99b214cf Size: 11.78kB Top Layer of: [docker.io/library/wordpress:latest]对该输出的解读要点头部信息Image ID是被查询镜像的完整 IDTags列出本地为该镜像保存的全部 tagSize是该镜像所有层数据的总大小本示例约 429.9MB。层列表自顶向下首行为最底层末行为顶层列出每一层的短 ID 与其大小。层大小单位会自适应显示kB / MB注意字节数为 1024 进制。Top Layer of标注当某层恰为本地某 tag 的顶层时给出提示。例如示例中80715f9e8880这一层是docker.io/library/php:7.2-apache的顶层而748e99b214cf是docker.io/library/wordpress:latest的顶层——这说明 wordpress 镜像是在 php:7.2-apache 之上又叠加了若干层构建出来的二者共享了下方绝大部分层。示例二查看指定镜像的子镜像与层--whatrequires$ podman image tree ae96a4ad4f3f --whatrequires Image ID: ae96a4ad4f3f Tags: [docker.io/library/ruby:latest] Size: 894.2MB Image Layers └── ID: 9c92106221c7 Size: 2.56kB Top Layer of: [docker.io/library/ruby:latest] ├── ID: 1b90f2b80ba0 Size: 3.584kB │ ├── ID: 42b7d43ae61c Size: 169.5MB │ ├── ID: 26dc8ba99ec3 Size: 2.048kB │ ├── ID: b4f822db8d95 Size: 3.957MB │ ├── ID: 044e9616ef8a Size: 164.7MB │ ├── ID: bf94b940200d Size: 11.75MB │ ├── ID: 4938e71bfb3b Size: 8.532MB │ └── ID: f513034bf553 Size: 1.141MB ├── ID: 1e55901c3ea9 Size: 3.584kB ├── ID: b62835a63f51 Size: 169.5MB ├── ID: 9f4e8857f3fd Size: 2.048kB ├── ID: c3b392020e8f Size: 3.957MB ├── ID: 880163026a0a Size: 164.8MB ├── ID: 8c78b2b14643 Size: 11.75MB ├── ID: 830370cfa182 Size: 8.532MB └── ID: 567fd7b7bd38 Size: 1.141MB Top Layer of: [docker.io/circleci/ruby:latest]该示例的解读要点以ae96a4ad4f3f即docker.io/library/ruby:latest为根输出一棵向下生长的树9c92106221c7是 ruby:latest 的顶层其下通过缩进与树形连线展开的是依赖它的子镜像所新增的层末行的Top Layer of: [docker.io/circleci/ruby:latest]表明567fd7b7bd38是本地circleci/ruby镜像的顶层——也就是说circleci/ruby 是在本机 ruby 镜像之上构建的二者共享基座对比上下两个分支可以看到子镜像引入的层大小差异可能很大如 169.5MB 的运行时层 vs 2.048kB 的元数据层这有助于判断某个下游镜像相对父镜像多加了什么。底层实现CLI → 引擎 → 存储的完整调用链podman image tree的 CLI 层非常薄tree.go 中的核心逻辑只有几步调用镜像引擎的Tree方法然后直接打印返回的树形字符串func tree(_ *cobra.Command, args []string) error { results, err : registry.ImageEngine().Tree(registry.Context(), args[0], treeOpts) if err ! nil { return err } fmt.Println(results.Tree) return nil }本地引擎实现ABI 模式在本地libpod/ABI模式下实现位于 pkg/domain/infra/abi/images.gofunc (ir *ImageEngine) Tree(ctx context.Context, nameOrID string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) { image, _, err : ir.Libpod.LibimageRuntime().LookupImage(nameOrID, nil) if err ! nil { return nil, err } tree, err : image.Tree(ctx, opts.WhatRequires) if err ! nil { return nil, err } return entities.ImageTreeReport{Tree: tree}, nil }关键点首先通过LookupImage(nameOrID, nil)解析镜像参数支持名称/tag/ID 三种形式解析失败会直接返回错误随后调用容器/镜像存储层libimage中Image.Tree(ctx, whatRequires)方法由它读取 layers 元数据并生成树形字符串返回值封装在entities.ImageTreeReport中其定义位于 pkg/domain/entities/types/images.go仅含一个Tree string字段——整个输出在引擎侧已格式化完毕。远程模式实现Tunnel当使用podman-remote或--remote连接远程服务时走的是 Tunnel 实现位于 pkg/domain/infra/tunnel/images.gofunc (ir *ImageEngine) Tree(_ context.Context, nameOrID string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) { options : new(images.TreeOptions).WithWhatRequires(opts.WhatRequires) return images.Tree(ir.ClientCtx, nameOrID, options) }它把本地选项翻译成 REST API 请求images.TreeOptions通过 HTTP 客户端调用远程服务端实现远程镜像、本地看树的效果。REST API 端点远程模式下服务端对应的 REST 处理函数位于 pkg/api/handlers/libpod/images.go。该端点解析 URL 查询参数whatrequires默认false构造entities.ImageTreeOptions后调用与本地完全相同的 ABIir.Tree(...)实现。也就是说本地、远程、API 三条路径最终汇聚到同一个 libimage 层树生成逻辑输出格式天然一致。镜像不存在时storage.ErrImageUnknown返回 404其余错误返回 500。与镜像引擎接口的对应关系Tree方法被声明在镜像引擎接口中见 pkg/domain/entities/engine_image.goTree(ctx context.Context, nameOrID string, options ImageTreeOptions) (*ImageTreeReport, error)接口与 ABI/Tunnel 两套实现的分离是 Podman 支持同一套 CLI 既可本地运行、也可连接远程服务的关键架构设计podman image tree正是理解这一架构的绝佳范例。实战场景与建议结合上面的层级结构与选项语义podman image tree典型应用于以下场景镜像体积排查定位哪一层占了大部分空间。示例一中 213.6MB 的b2d6a702383c与 58.47MB 的底层立刻暴露了体积大头可据此决定是否改用更精简的基础镜像。层共享分析通过Top Layer of标注判断本地镜像间的复用关系。若多个 tag 共享底层删除其中某个镜像时其余镜像不受影响若想验证新打的 tag 是否真的复用了旧层直接看树即可。派生关系追踪用--whatrequires以某个基础镜像为根找出本地所有基于它构建的子镜像评估升级或删除基础镜像的波及范围。镜像审计与教学直观展示分层存储模型帮助理解docker build中每条RUN产生一层的原理以及为什么减少层数、合并 RUN能优化镜像。需要提醒的边界该命令输出的是本地存储中的层信息未拉取到本地的镜像无法查询Size为该层在本地存储中占用的空间含压缩/展开差异不代表镜像在注册表中的传输大小。具体层数据由底层存储驱动如 overlayfs、vfs经由libimage提供仓库中的镜像拉取与存储管理逻辑可参见 libpod/runtime_img.go 与 libpod/storage.go。相关文档命令手册podman-image-tree.1.md主命令手册podman(1)命令实现cmd/podman/images/tree.go本地引擎实现pkg/domain/infra/abi/images.go远程引擎实现pkg/domain/infra/tunnel/images.goREST API 处理pkg/api/handlers/libpod/images.go选项与返回值定义pkg/domain/entities/images.go、pkg/domain/entities/types/images.go该命令自 2019 年 2 月由 Kunal Kushwaha 整理成文档见手册 HISTORY 节至今仍是 Podman 镜像分析工具链中稳定且常用的一员。赞分享容器运行时云原生CLI【免费下载链接】podmanPodman: A tool for managing OCI containers and pods.项目地址https://gitcode.com/gh_mirrors/po/podman点击查看免费下载相关推荐Podman 网络清理实战深入解析 podman network prune 命令与底层实现Podman 网络清理实战深入解析 podman network prune 命令与底层实现 podman network prune 是 Podman 提供容器运行时云原生CLIPodman 镜像删除实战指南深入解析 podman rmi / podman image rm 命令Podman 镜像删除实战指南深入解析 podman rmi / podman image rm 命令 podman rmi 及其等价别名 podman i容器运行时云原生CLI如何用Python教会AI在GTA5中自动驾驶从游戏到AI训练场的奇幻之旅如何用Python教会AI在GTA5中自动驾驶从游戏到AI训练场的奇幻之旅 想象一下你坐在电脑前看着屏幕上的虚拟汽车在洛圣都的街道上自如穿梭——加速、转弯容器运行时云原生CLI上一篇CVAT 第三方模型接入实践serverless 部署与自动标注全链路下一篇Flipper Zero 中文显示从乱码方块到中文界面的完整实操路径创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表