news 2026/9/20 21:32:14

Podman Compose 多网络容器测试解析:验证容器同时接入多个 Compose 网络

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Podman Compose 多网络容器测试解析:验证容器同时接入多个 Compose 网络
  • 容器运行时
  • 云原生
  • CLI

【免费下载链接】podman

Podman: A tool for managing OCI containers and pods.

项目地址:https://gitcode.com/gh_mirrors/po/podman
点击查看免费下载

容器接入多个网络是 Compose 工作负载中常见的拓扑需求(例如业务网络与存储网络分离、服务同时暴露在管理网与业务网)。本文以 Podman 仓库中的 compose 集成测试用例two_networks为主线,完整讲解其配置写法、验证命令、底层数据结构与测试框架的运行机制,帮助你掌握"如何用 Compose 定义多网络服务"以及"如何在 Podman 上可靠地验证容器确实同时处于多个网络"。

一、测试用例定位:它在验证什么

在 Podman 仓库中,test/compose/目录下存放着一组针对 docker-compose v2 的集成测试,每个子目录对应一个独立场景。test/compose/two_networks/Readme.md是该用例的说明文档,全文虽短,但定义了一个非常明确的验收标准:

  • 测试目的:验证 Podman 能够创建同时接入不止一个网络(more than one network)的容器;
  • 验收命令
podman container inspect two_networks_con1_1 --format '{{len .NetworkSettings.Networks}}'
  • 期望结果:输出2,即该容器的NetworkSettings.Networks中记录了 2 个网络。

这一条命令是整个用例的灵魂:它通过 Go template 对podman container inspect的 JSON 输出取长度,从而断言容器同时连接到了两个网络。相关文件包括:

  • test/compose/two_networks/Readme.md
  • test/compose/two_networks/docker-compose.yml
  • test/compose/two_networks/tests.sh

二、Compose 配置:让一个服务加入两个网络

two_networks用例的docker-compose.yml是完整的、可复现的示例(约 12 行),其核心写法如下:

version: '3' services: con1: image: alpine command: top networks: - net1 - net2 networks: net1: net2:

拆解这个配置:

片段作用说明
services.con1.image: alpine使用基础镜像alpine体积小,适合作为常驻进程测试载体
services.con1.command: top让容器保持前台运行避免容器因无前台进程而立即退出,top保证容器处于运行态
services.con1.networks: [net1, net2]声明服务接入多个网络这是"多网络"的关键——在同一服务下罗列两个网络名
networks.net1 / net2顶层网络定义Compose 会自动为每个顶层网络创建对应的 Podman 网络

要点:在 Compose 规范中,一个服务(service)的networks字段是一个列表,列出该服务要加入的全部网络;顶层networks段则声明这些网络的属性(此处为空,表示使用默认配置)。Compose 将按项目名_网络名的规则为网络命名,这也是后面测试断言中网络名前缀为two_networks_的原因。

三、验证逻辑:inspect 与 Go template 的用法

测试用例的核心验证逻辑位于 test/compose/two_networks/tests.sh,它比 Readme 中的单条命令更完整,共包含三步断言:

# -*- bash -*- ctr_name="two_networks-con1-1" podman container inspect "$ctr_name" --format '{{len .NetworkSettings.Networks}}' is "$output" "2" "$testname : Container is connected to both networks" podman container inspect "$ctr_name" --format '{{.NetworkSettings.Networks}}' like "$output" "two_networks_net1" "$testname : First network name exists" like "$output" "two_networks_net2" "$testname : Second network name exists"

逐步解读:

  1. 容器名约定:Compose 项目名取自目录名two_networks,服务名con1的实例默认命名为<项目名>-<服务名>-<序号>,因此这里用two_networks-con1-1。(注意:Readme 中写的是two_networks_con1_1,带下划线;tests.sh 中实际使用的是带连字符的two_networks-con1-1,这与 docker-compose v2 的实际命名规则一致,后者才是运行时真正生效的容器名。)
  2. 数量断言{{len .NetworkSettings.Networks}}对 inspect JSON 中的NetworkSettings.Networks映射取元素个数,is断言其严格等于2,证明容器同时连接了两个网络。
  3. 成员断言{{.NetworkSettings.Networks}}直接打印整个网络映射,like断言输出中同时包含two_networks_net1two_networks_net2两个网络名,证明连接的是正确的、预期的两个网络(而非任意两个)。

这一"先验数量、再验成员"的验证模式在整个 Podman 测试体系中反复出现。例如 test/e2e/network_connect_disconnect_test.go 中同样使用--format '{{len .NetworkSettings.Networks}}'来断言网络连接/断开后容器所连网络的数量变化,还进一步使用{{(index .NetworkSettings.Networks "网络名").Aliases}}DNSNames验证单个网络的别名与 DNS 记录——如果你想做更细粒度的多网络验证(如确认每个网络内的别名、DNS 解析),可以参考该文件的写法。

四、底层数据结构:NetworkSettings.Networks 从哪来

{{len .NetworkSettings.Networks}}之所以能工作,是因为podman container inspect的输出结构在源码中有明确定义。在 libpod/define/container_inspect.go 中:

// InspectNetworkSettings holds information about the network settings of the // container. // Many fields are maintained only for compatibility with `docker inspect` and // are unused within Libpod. type InspectNetworkSettings struct { InspectBasicNetworkConfig Bridge string `json:"Bridge"` SandboxID string `json:"SandboxID"` HairpinMode bool `json:"HairpinMode"` LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"` LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"` Ports map[string][]InspectHostPort `json:"Ports"` SandboxKey string `json:"SandboxKey"` // Networks contains information on non-default networks this // container has joined. // It is a map of network name to network information. Networks map[string]*InspectAdditionalNetwork `json:"Networks,omitempty"` }

从中可以得到几个关键事实:

  • Networks是一个以网络名为 key的 map,{{len .NetworkSettings.Networks}}得到的就是容器所加入网络的个数;
  • 该结构刻意保持与docker inspect输出兼容(源码注释明确说明"Many fields are maintained only for compatibility withdocker inspect"),因此对 Docker 用户而言字段语义可直接迁移;
  • 每个网络的值类型是InspectAdditionalNetwork,其中包含该网络下容器的别名(Aliases)、DNS 名称(DNSNames)、静态 IP/MAC 等信息——这正是 e2e 测试中用(index .NetworkSettings.Networks "net").Aliases取单网络细节的原因。

从源码结构可以推断:只要容器通过任何方式(Compose 编排、podman network connect--network多网络参数)加入了多个网络,这些网络都会以"网络名 → 网络详情"的条目出现在NetworkSettings.Networks中,因此len的返回值能作为"多网络"是否成立的通用判据。

五、测试框架:test-compose 如何运行该用例

two_networks不是孤立脚本,而是由 test/compose/test-compose 统一驱动的用例之一。根据 test/compose/README.md 与脚本实现,其运行流程为:

  1. 在临时工作目录下建立全新的 Podman root/runroot;
  2. podman system service --time 0 unix://$DOCKER_SOCK方式启动一个基于本地 Unix socket 的 Podman API 服务;
  3. cd进入用例子目录,执行docker-compose up -d(后台拉起服务);
  4. source该目录下的tests.sh,执行其中的断言(即上一节的 inspect 校验);
  5. 执行docker-compose down清理,然后杀掉 API 服务进程。

运行方式(默认运行所有 compose 用例,也可用模式限定单个用例):

$ sudo test/compose/test-compose [pattern]

例如只跑本用例:

$ sudo test/compose/test-compose two_networks

脚本还针对 rootless 场景做了适配:rootless 下会把 Docker socket 放到工作目录内,并通过podman system connection add compose-sock "unix://$DOCKER_SOCK"注册连接、设置PODMAN_CONNECTIONS_CONF以免覆盖用户配置,再以podman --connection compose-sock compose ...驱动 compose provider。脚本默认导出PODMAN_COMPOSE_WARNING_LOGS=false,以避免 compose provider 的引擎提示干扰对 stderr 的断言。

调试技巧:设置COMPOSE_WAIT=1可让脚本在执行down之前暂停,方便你在另一个终端里用独立 root 检查容器状态:

$ env COMPOSE_WAIT=1 sudo --preserve-env=COMPOSE_WAIT test/compose/test-compose two_networks # 另一个终端: # podman --root $X/root --runroot $X/runroot ps -a # podman --root $X/root --runroot $X/runroot logs -l

六、前置知识:podman compose 是什么

要理解为什么该用例能用docker-compose up -d驱动 Podman,需要知道podman compose的本质。在 cmd/podman/compose.go 中,compose命令被明确定义为:

"a thin wrapper around an external compose provider such as docker-compose or podman-compose"(对外部 compose provider 的薄封装)

也就是说,Podman 本身并不实现 Compose 编排逻辑,而是:

  • 按顺序查找可用的外部 provider(默认候选为docker-composepodman-compose,docker-compose 优先);也可通过环境变量PODMAN_COMPOSE_PROVIDER或 containers.conf 的[engine]表中compose_providers字段指定;
  • 在调用 provider 前注入环境变量:将DOCKER_HOST指向本地 Podman API socket(unix://默认地址或podman machine连接),并设置DOCKER_BUILDKIT=0(Podman 不追踪全部 buildkit 特性)、透传DOCKER_CONFIG
  • podman compose之后的所有参数原样透传给外部 provider,并将 provider 的退出码作为自己的退出码返回。

正是这种"环境重定向 + 参数透传"机制,让 docker-compose v2 可以把网络创建、容器启动等 API 调用全部落到 Podman 上,从而让"容器接入多个 Compose 网络"在 Podman 下成为现实。这也解释了本用例为什么命名为"two networks"集成测试:它在验证 Docker Compose 的多网络语义在 Podman 兼容层上的端到端表现。

七、手动复现与扩展验证

不借助测试框架,你也可以手动复现该用例的完整链路:

# 1. 创建项目目录与配置文件 mkdir -p ~/two_networks_demo && cd ~/two_networks_demo # 内容即上文第二节的 docker-compose.yml # 2. 启动服务 podman compose up -d # 3. 执行与 Readme 一致的验收命令,期望输出 2 podman container inspect two_networks-con1-1 --format '{{len .NetworkSettings.Networks}}' # 4. 查看容器实际接入的网络明细 podman container inspect two_networks-con1-1 --format '{{.NetworkSettings.Networks}}' # 5. 清理 podman compose down

如果需要进一步验证每个网络内的细节,可参考 e2e 测试的写法(见第三节),使用index语法按网络名取值:

podman container inspect two_networks-con1-1 \ --format '{{(index .NetworkSettings.Networks "two_networks_net1").Aliases}}' podman container inspect two_networks-con1-1 \ --format '{{(index .NetworkSettings.Networks "two_networks_net1").DNSNames}}'

八、小结

two_networks这个看似只有两行说明的用例,实际覆盖了一条完整的验证链:Compose 侧通过networks列表声明多网络,Podman 兼容层通过注入DOCKER_HOST承接 docker-compose 的网络 API,容器运行时把多个网络记录进NetworkSettings.Networks,测试侧则用{{len .NetworkSettings.Networks}}{{.NetworkSettings.Networks}}分别验证"数量为 2"与"成员为预期的两个网络"。阅读本文后,你既能照抄它的配置与命令完成自己的多网络容器验证,也能顺着 test/compose/test-compose、cmd/podman/compose.go 与 libpod/define/container_inspect.go 三条源码线索,理解这一能力从编排到 inspect 的完整实现路径。

  • 容器运行时
  • 云原生
  • CLI

【免费下载链接】podman

Podman: A tool for managing OCI containers and pods.

项目地址:https://gitcode.com/gh_mirrors/po/podman
点击查看免费下载
上一篇:Redisson分布式任务分片执行与结果聚合终极指南
下一篇:Actix Web代码组织策略:大型项目的目录结构设计

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 21:32:08

QuickRecorder:一个不到 10MB 的免费 macOS 录屏工具

QuickRecorder&#xff1a;一个不到 10MB 的免费 macOS 录屏工具 【免费下载链接】QuickRecorder A lightweight screen recorder based on ScreenCapture Kit for macOS / 基于 ScreenCapture Kit 的轻量化多功能 macOS 录屏工具 项目地址: https://gitcode.com/GitHub_Tren…

作者头像 李华
网站建设 2026/9/20 21:28:37

Atlas 300V 24G加速卡解读:昇腾NPU上部署YOLO全流程实战

上周同事在项目群里甩过来一张截图&#xff0c;问题写得很直接&#xff1a;Atlas 300V 24G 是运算加速卡吗&#xff1f;看到这个问题我一下就笑了&#xff0c;因为一个月前我刚拿到这张卡时的反应一模一样——把它插进服务器PCIe槽&#xff0c;开机&#xff0c;习惯性敲nvidia-…

作者头像 李华
网站建设 2026/9/20 21:28:17

PolarDB Agent Express:企业级AI Agent PaaS的架构拆解与落地指南

最近在社区里看到不少人在讨论一个叫PolarDB Agent Express的产品名。奇怪的是&#xff0c;问法高度一致&#xff1a;"它到底是个独立产品&#xff0c;还是一堆东西拼起来的组合&#xff1f;"、"它和数据库是什么关系&#xff1f;"、"这名字看起来像个…

作者头像 李华
网站建设 2026/9/20 21:25:37

MCX:GPU加速蒙特卡洛光子传输模拟器的原理与实战

简介&#xff1a;MCX&#xff08;Monte Carlo eXtreme&#xff09;是一款基于蒙特卡洛方法的GPU加速三维光子传输模拟器&#xff0c;面向生物医学光子学、光电子学与光学工程领域的研究者&#xff0c;解决了传统CPU模拟在复杂介质中速度慢、耗时久的问题。该开源资源包共684个文…

作者头像 李华
网站建设 2026/9/20 21:24:06

使用 Chrome DevTools 调试 AVA 测试:debug 命令实战与原理剖析

使用 Chrome DevTools 调试 AVA 测试&#xff1a;debug 命令实战与原理剖析 【免费下载链接】ava Node.js test runner that lets you develop with confidence &#x1f680; 项目地址: https://gitcode.com/gh_mirrors/ava/ava 本文聚焦 AVA&#xff08;Node.js test …

作者头像 李华
网站建设 2026/9/20 21:20:26

Worktree 并行跑多个 Claude Code 任务:Key 用 TaoToken

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

作者头像 李华