关于docker容器,Connection refused

2024-06-01

关于上一篇文章中,遇到了一个操蛋的问题,将我的RPC服务端运行在docker容器中时。在其他docker容器中访问RPC服务时,总是Connection refused

问题排查

1.测试网络连通性(ping)

我在另外一个容器中访问RPC服务时,是以 容器名称:端口号 的形式访问RPC服务的,本来我以为是两个容器之间网络不通导致服务无法连接。

但是进入容器中使用ping测试,是可以互相连通的。所以排除网络不通的原因

2.测试接口响应(curl)

当我进入RPC服务器容器时,用curl命令测试。

curl http://127.0.0.1:8000

虽然返回的是501,但证明服务时可访问的,只是访问的姿势不对。

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: 501</p>
        <p>Message: Unsupported method ('GET').</p>
        <p>Error code explanation: 501 - Server does not support this operation.</p>
    </body>
</html>

在容器外宿主机测试(注:我做了端口映射,将宿主机的8000端口映射到容器内部的8000端口)

curl http://127.0.0.1:8000

Connection reset by peer,连接被重置 ----> 连接不通

curl: (56) Recv failure: Connection reset by peer

请求无法到达我RPC服务。但是端口都对的上的呀,为什么访问不到,在内网访问时,也涉及不到防火墙策略啥的。到底是为什么呢????

错误解决

就不搞那么多弯弯绕绕了,直接说错误是什么,该怎么解决,上面主要是展示我排错的过程,或许可以值得借鉴一下。

直接上代码

如下,我的RPC服务监听的是本机的8000端口,所以在上面进入docker容器中可以访问到服务。

# Create server
with SimpleXMLRPCServer(('localhost', 8000),requestHandler=RequestHandler) as server:
    server.register_introspection_functions()
    server.register_instance(RpcMethodsHanlers())
    server.serve_forever()

那为什么,我在容器外部就访问不到了呢,我也做了端口映射的呀。

问题就出现在localhost !!!!

进入docker容器,使用ifconfig 查看接口配置,可以看到有两个接口,eth0

和lo,而我的RPC服务监听的就是lo这个接口,127.0.0.1(等同于localhost)

/app # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:C0:A8:2F:04  
          inet addr:192.168.47.4  Bcast:192.168.47.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1203 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1185 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3185826 (3.0 MiB)  TX bytes:65576 (64.0 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1264 (1.2 KiB)  TX bytes:1264 (1.2 KiB)

eth0是负责与docker网络通信的接口,其ip地址也是docker网络分配的,当我们在docker外部访问该docker容器时,最终是与这个接口通信。

如下图,我的RPC服务监听的是lo接口,而请求最终转发到了eth0,导致了Connection refused

解决办法

监听0.0.0.0

注:

通配符地址:在某些情况下,0.0.0.0 可以用作通配符地址,表示所有可能的 IP 地址。例如,在服务器中,当一个服务绑定到 0.0.0.0 时,它将监听来自本地网络接口和所有网络接口的连接。

# Create server
with SimpleXMLRPCServer(('0.0.0.0', 8000),requestHandler=RequestHandler) as server:
    server.register_introspection_functions()
    server.register_instance(RpcMethodsHanlers())
    server.serve_forever()

此时的效果。问题得到解决。

总结

当我们在docker容器内部可以正常访问服务,而在外部无法访问服务时,

最可能就是请求没有转发到服务监听的接口。

PREV
什么是RPC协议?
NEXT
python使用RPC