草庐IT

linux - 为什么 Docker 容器无法相互通信?

coder 2023-06-20 原文

我创建了一个小的 project测试 Docker 集群。基本上,cluster.sh 脚本会启动三个相同的容器,并使用 pipework在主机上配置网桥(bridge1)并为每个容器添加网卡(eth1)。

如果我登录其中一个容器,我可以arping其他容器:

# 172.17.99.1
root@d01eb56fce52:/# arping 172.17.99.2
ARPING 172.17.99.2
42 bytes from aa:b3:98:92:0b:08 (172.17.99.2): index=0 time=1.001 sec
42 bytes from aa:b3:98:92:0b:08 (172.17.99.2): index=1 time=1.001 sec
42 bytes from aa:b3:98:92:0b:08 (172.17.99.2): index=2 time=1.001 sec
42 bytes from aa:b3:98:92:0b:08 (172.17.99.2): index=3 time=1.001 sec
^C
--- 172.17.99.2 statistics ---
5 packets transmitted, 4 packets received,  20% unanswered (0 extra)

所以数据包似乎可以通过bridge1

但问题是我无法ping 其他容器,我也无法通过telnetnetcat 等任何工具发送任何IP 数据包.

相比之下,网桥 docker0 和 NIC eth0 在所有容器中都能正常工作。

这是我的路由表

# 172.17.99.1
root@d01eb56fce52:/# ip route
default via 172.17.42.1 dev eth0 
172.17.0.0/16 dev eth0  proto kernel  scope link  src 172.17.0.17 
172.17.99.0/24 dev eth1  proto kernel  scope link  src 172.17.99.1

和网桥配置

# host
$ brctl show
bridge name bridge id       STP enabled interfaces
bridge1     8000.8a6b21e27ae6   no      veth1pl25432
                                        veth1pl25587
                                        veth1pl25753
docker0     8000.56847afe9799   no      veth7c87801
                                        veth953a086
                                        vethe575fe2

# host
$ brctl showmacs bridge1
port no mac addr        is local?   ageing timer
  1 8a:6b:21:e2:7a:e6   yes        0.00
  2 8a:a3:b8:90:f3:52   yes        0.00
  3 f6:0c:c4:3d:f5:b2   yes        0.00

# host
$ ifconfig
bridge1   Link encap:Ethernet  HWaddr 8a:6b:21:e2:7a:e6  
          inet6 addr: fe80::48e9:e3ff:fedb:a1b6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:163 errors:0 dropped:0 overruns:0 frame:0
          TX packets:68 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:8844 (8.8 KB)  TX bytes:12833 (12.8 KB)

# I'm showing only one veth here for simplicity
veth1pl25432 Link encap:Ethernet  HWaddr 8a:6b:21:e2:7a:e6  
          inet6 addr: fe80::886b:21ff:fee2:7ae6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:155 errors:0 dropped:0 overruns:0 frame:0
          TX packets:162 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:12366 (12.3 KB)  TX bytes:23180 (23.1 KB)

...

和IP FORWARD链

# host
$ sudo iptables -x -v --line-numbers -L FORWARD
Chain FORWARD (policy ACCEPT 10675 packets, 640500 bytes)
num      pkts      bytes target     prot opt in     out     source               destination         
1       15018 22400195 DOCKER     all  --  any    docker0  anywhere             anywhere            
2       15007 22399271 ACCEPT     all  --  any    docker0  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3        8160   445331 ACCEPT     all  --  docker0 !docker0  anywhere             anywhere            
4          11      924 ACCEPT     all  --  docker0 docker0  anywhere             anywhere            
5          56     4704 ACCEPT     all  --  bridge1 bridge1  anywhere             anywhere            

请注意规则 5 的 pkts cound 不是 0,这意味着 ping 已被正确路由(FORWARD 链在路由后执行对吧?),但不知何故没有到达目的地。

我不明白为什么 docker0bridge1 表现不同。有什么建议吗?

更新 1

这是从另一个 ping 时目标容器上的 tcpdump 输出。

$ tcpdump -i eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
22:11:17.754261 IP 192.168.1.65 > 172.17.99.1: ICMP echo request, id 26443, seq 1, length 6

请注意源 IP 是 192.168.1.65,这是主机的 eth0,因此网桥上似乎正在进行一些 SNAT。

最后,打印出nat IP表,问题的原因就出来了:

$ sudo iptables -L -t nat
...
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere
...

因为我容器的 eth0 的 IP 在 172.17.0.0/16 上,所以发送的数据包的源 IP 已更改。这就是 ping 的响应无法返回源头的原因。

结论

解决方案是将容器的 eth0 的 IP 更改为与默认 docker0 不同的网络。

最佳答案

Copied from Update 1 in question

这是从另一个 ping 时目标容器上的 tcpdump 输出。

$ tcpdump -i eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
22:11:17.754261 IP 192.168.1.65 > 172.17.99.1: ICMP echo request, id 26443, seq 1, length 6

请注意源 IP 是 192.168.1.65,这是主机的 eth0,因此网桥上似乎正在进行一些 SNAT。

最后,打印出nat IP表,问题的原因就出来了:

$ sudo iptables -L -t nat
...
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere
...

因为我容器的 eth0 的 IP 在 172.17.0.0/16 上,所以发送的数据包的源 IP 已更改。这就是 ping 的响应无法返回源头的原因。

结论

解决方案是将容器的 eth0 的 IP 更改为与默认 docker0 不同的网络。

关于linux - 为什么 Docker 容器无法相互通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31904089/

有关linux - 为什么 Docker 容器无法相互通信?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  7. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  8. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  9. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  10. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

随机推荐