Docker容器内服务可内部访问但主机访问时浏览器及curl挂起无响应问题排查求助
Docker容器内服务可内部访问但主机访问时浏览器及curl挂起无响应问题排查求助
我在Ubuntu主机上用Docker运行了几个Web应用,每个应用监听不同端口。现在遇到一个特别头疼的问题:在Docker网络内的任意容器里,我都能正常连接并获取服务返回的数据,但从主机发起请求时,虽然能成功建立连接,却完全收不到任何数据。浏览器访问localhost:8080会一直挂起,curl也是无限等待,这到底是哪里出问题了?
端口映射与监听状态确认
先看docker ps的端口输出,显示映射是正常的:
0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
用netstat检查主机端口监听情况,也显示8080端口处于监听状态:
$ netstat -anp | grep 8080 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN - tcp6 0 0 :::8080 :::* LISTEN -
主机访问的异常表现
不管是用Firefox还是Chrome访问localhost:8080,浏览器都会一直加载,没有任何响应返回。用curl测试也是一样,连接建立后就卡住了:
$ curl -vvv localhost:8080 * Uses proxy env variable no_proxy == 'localhost,127.0.0.1,::1' * Trying 127.0.0.1:8080... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 8080 (#0) > GET / HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.68.0 > Accept: */* > ^C
我还用telnet试过,结果也是连接上后就没有任何数据返回,一直挂着。
对比测试:主机直接运行服务正常
为了排除主机本身的网络问题,我在主机上直接启动了一个Python HTTP服务:
python3 -m http.server 8000
用curl访问这个服务完全正常,能收到响应:
$ curl -vvv localhost:8000 * Uses proxy env variable no_proxy == 'localhost,127.0.0.0/8,::1' * Trying 127.0.0.1:8000... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 8000 (#0) > GET / HTTP/1.1 > Host: localhost:8000 > User-Agent: curl/7.68.0 > Accept: */* > * Mark bundle as not supporting multiuse * HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Server: SimpleHTTP/0.6 Python/3.8.13 < Date: Fri, 09 Dec 2022 12:36:03 GMT < Content-type: text/html; charset=utf-8 < Content-Length: 16768 < <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> ...
我也尝试直接访问容器的IP地址(比如172.17.0.3:8080),结果还是一样,连接建立后没有响应。但反过来,在容器内部用curl访问其他容器的HTTP端点,却完全正常。
Docker Compose相关配置(docker inspect截取内容)
我是用Docker Compose部署的,docker inspect返回的部分配置如下:
"HostConfig": { "Binds": [], ... "NetworkMode": "docker-compose-example_default", "PortBindings": { "8080/tcp": [ { "HostIp": "", "HostPort": "8080" } ] }, ... "NetworkSettings": { "Bridge": "", "SandboxID": "1b53a5b6580187b714c6d7d0c9f81a015d585cd0bb0d62da579a4fe7514d47ea", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "8080/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "8080" }, { "HostIp": "::", "HostPort": "8080" } ] }, "SandboxKey": "/var/run/docker/netns/1b53a5b65801", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": { "docker-compose-example_default": { "IPAMConfig": null, "Links": null, "Aliases": [ "dc0813038a3b", "adminer" ], "NetworkID": "65c6700f5445a6ce0f98a0a4e14e3e10577f40706411f639a4f9da5b1cfdd52e", "EndpointID": "0f42ae8ce893fb4f33168c31df0d5de38d2e8ca67521802ba76589a8a0cb1bea", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:03", "DriverOpts": null } } }
问题总结
现在情况就是:
- 容器内部可以正常访问所有服务的HTTP端点
- 主机上直接运行的服务可以正常被访问
- Docker端口映射显示正常,主机端口也处于监听状态
- 主机访问容器服务时,连接能建立,但完全收不到响应,请求一直挂起
我怀疑是Docker桥接网络出了问题,但不知道具体该怎么排查和修复。有没有大佬能指点一下,我该怎么调整才能让主机正常访问Docker容器内的服务?
备注:内容来源于stack exchange,提问作者thayne




