在 Podman 的世界里,我们经常被问到的一个问题是:“为什么我的容器无法通过名称解析其他容器?” 在很多情况下,答案是……因为你正在一个禁用了名称解析的网络上运行。实际上,你很可能正在运行在*默认*网络上;而这个默认网络确实没有启用名称解析。接下来的问题是“为什么 Podman 会这样做?” 标准答案是什么?“因为 Docker 就是这样做的,人们希望尽可能与 Docker 兼容。”
我们通过例子来仔细看看。我将使用由特权用户创建的容器,因为这有点像是 Docker 的标准。在每个例子中,我都会在同一个网络上启动两个命名容器,并展示名称解析的成功和失败。
在第一个例子中,我们确认只有默认的 Podman 网络存在。它被称为 podman,并且无法删除。请记住,默认网络没有启用名称解析,任何尝试这样做都应该并且确实会失败。请注意,test2 无法通过名称解析 test1。
$ sudo podman network ls NETWORK ID NAME DRIVER 2f259bab93aa podman bridge $ sudo podman run --rm -dt --name test1 alpine top 3703d80740513421772db407972111ad6f535f5ca214f11ddb714a7d64ee140c $ sudo podman run --rm -it --name test2 alpine /bin/sh / # ping test1 ping: bad address 'test1' / # exit
一个解决方案是创建一个我称之为 new 的新网络。默认情况下,所有创建的网络都启用了名称解析,并且必须选择禁用它。然后我以与以前相同的方式运行两个容器,只是我引用了不同的网络,并且名称解析按预期工作。
$ sudo podman network create new new $ sudo podman network ls NETWORK ID NAME DRIVER d9376e135b46 new bridge 2f259bab93aa podman bridge $ sudo podman run --rm -dt --name test1 --network new alpine top f5a8d256f29221676dc7fca36bca0b680dd7de4a5aa20af2a9d9a02072b34fc7 $ sudo podman run --rm -it --name test2 --network new alpine /bin/sh / # ping test1 PING test1 (10.89.0.2): 56 data bytes 64 bytes from 10.89.0.2: seq=0 ttl=42 time=0.114 ms 64 bytes from 10.89.0.2: seq=1 ttl=42 time=0.107 ms ^C
我之前提到过,Podman 出现这种行为的原因之一是 Docker 也是如此。使用 Docker 的默认网络进行相同的测试,我们可以看到名称解析也不起作用。解决方案与 Podman 相同,即您创建一个新网络并在那里运行您的容器。
ubuntu@ubuntu:~$ sudo docker network ls NETWORK ID NAME DRIVER SCOPE cb0c4d38339a bridge bridge local 5d0fce56bcad host host local 18c31437e8d0 none null local ubuntu@ubuntu:~$ sudo docker run -dt --name test1 alpine top b23e15c969d253f33f99bd2cecb00b4b061e2a7605190eae683f546692ea34cc ubuntu@ubuntu:~$ sudo docker run -it --name test2 alpine /bin/sh / # ping test1 ping: bad address 'test1' / # exit
如果您总是希望您的容器具有名称解析功能,但又不想为每个容器引用不同的网络,您可以将任何网络设为容器的默认网络。这需要对 /etc/containers/containers.conf 进行少量更改(如果 containers.conf 不存在,则只需简单添加)。
$ sudo cat /etc/containers/containers.conf [network] default_network = "new" $ sudo podman run -dt --rm --name test1 alpine top 18d033aeec0640100bf8165c23b01e55c03fbd5bc320d874a3f4f01f755512c7 $ sudo podman run -it --rm --name test2 alpine /bin/sh / # ping test1 PING test1 (10.89.0.5): 56 data bytes 64 bytes from 10.89.0.5: seq=0 ttl=42 time=0.137 ms 64 bytes from 10.89.0.5: seq=1 ttl=42 time=0.106 ms ^C --- test1 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.106/0.121/0.137 ms / # exit
这里请注意,new 是默认网络,并且名称解析正常工作。
我们也被问及 Podman 为什么要模仿 Docker 的这种行为,尤其是在很多人都希望默认启用名称解析的情况下。我个人的答案是双重的。我不知道 Docker 为什么这样做,我也不想去探究,而且 Podman 用户喜欢在我们与 Docker 不完全兼容时指责我们。我不希望默认启用名称解析的第二个原因是,容器运行需要稍微更长的时间。Podman 总是需要使用 netavark 来设置网络,但当启用名称解析时,netavark 还必须调用 aardvark-dns。所需的时间可能几乎可以忽略不计,但在某些情况下这很重要。

Brent Baude
高级首席软件工程师,Podman 架构师
回复 runiq取消回复