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 容器服务也就能顺利启动了。
但这只是一个临时措施,每次重启系统后您可能都需要再次手动执行。
方法三:自动触发 network-online.target
# /etc/systemd/system/podman-network-online-dummy.service
[Unit]
Description=This service simply activates network-online.target
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/bin/echo Activating network-online.target
[Install]
WantedBy=multi-user.target总结
Podman 容器启动卡住通常是由于其 systemd 服务依赖的 network-online.target 未被激活。在官方给出更完美的全局解决方案之前,目前这几种方法是最可靠的选择,但 podman 社区仍未关闭相关议题,还在积极寻找更可靠的根本性解决方案。