Podman 容器启动卡住?可能是 Network-Online.target 在作祟
问题现象
您是否遇到过在使用 podman
启动容器时,命令长时间卡住没有任何输出,也无法进入下一步的情况?尤其是在使用 systemd
或 Quadlet
来管理容器生命周期时,例如执行 systemctl --user start my-container.service
,命令卡住直到 90 秒超时。
这个问题在社区中时有讨论,例如在 Podman GitHub Issue #24796 中提到的相关网络问题,都可能导致类似的现象。
根本原因
这个问题的根源通常不在于 podman
本身,而在于 podman
与 systemd
的交互机制,特别是关于网络依赖的部分。
当您使用 Quadlet
(后缀为 .container
, .kube
, .volume
等文件) 创建 systemd
服务来管理容器时,生成的服务单元通常会包含一个依赖项:After=network-online.target
。
network-online.target
是 systemd
中一个特殊的目标(target),它表示系统的网络已经完全配置好并且可以访问。很多需要网络连接的服务(比如数据库、Web 服务,以及我们的容器)都会等待这个目标达成后再启动,以确保网络是可用的。
然而,在某些 Linux 发行版或特定的网络配置下,负责管理网络的组件(如 NetworkManager
或 systemd-networkd
)可能没有正确地通知 systemd
网络已经“在线”。这导致 network-online.target
永远不会被激活,而所有依赖于它的服务(包括您的 Podman 容器服务)也将永远地等待下去,从而造成了“卡住”的假象。
解决方案
针对这个问题,目前有两种有效的解决方案,您可以根据自己的情况选择。
方法一:修改 Quadlet 文件
如果您确认您的容器不需要等待网络完全就绪即可启动(例如,容器不立即对外提供服务,或者服务本身有重试机制),您可以直接在您的 .container
文件中禁用默认的网络依赖。
在对应的 Quadlet 文件(如 ~/.config/containers/systemd/my-container.container
)中,添加以下区段:
[Quadlet]
DefaultDependencies=false
这个配置会告诉 Quadlet 在生成 systemd
服务文件时,不要自动添加 After=network-online.target
这个依赖项。
修改后,需要重新加载 systemd
配置以使更改生效:
systemctl --user daemon-reload
之后,您就可以正常启动您的容器服务了,它将不再等待 network-online.target
。
这个方法的好处是它只针对特定的容器生效,并且是持久化的,不需要每次重启都手动干预。
方法二:手动触发 network-online.target
如果您急需启动容器,或者不想修改 Quadlet 文件,可以手动触发 network-online.target
。在终端中运行以下命令:
sudo systemctl start network-online.target
这个命令会手动将 network-online.target
标记为已激活状态,从而解除所有等待该目标的服务的阻塞状态,您的 Podman 容器服务也就能顺利启动了。
但这只是一个临时措施,每次重启系统后您可能都需要再次手动执行。
关于全局解决方案的讨论
一些用户尝试通过启用 NetworkManager-wait-online.service
来自动处理这个依赖,命令如下:
# 注意:此方法在社区反馈中并不可靠
sudo systemctl enable NetworkManager-wait-online.service
然而,根据相关 GitHub Issue 中的持续讨论,这种方法并不稳定,在很多场景下问题依旧存在。因此,podman
社区仍未关闭相关议题,还在积极寻找更可靠的根本性解决方案。
总结
Podman 容器启动卡住通常是由于其 systemd
服务依赖的 network-online.target
未被激活。在官方给出更完美的全局解决方案之前,这两种方法是最可靠的选择。希望这篇文章能帮助您解决这个令人困惑的问题。