Docker Compose跨容器服务端口可达性检测异常排查
问题诊断与解决方案
你遇到的核心矛盾是:TCP层面的socket连接检测失败,但HTTP层面的curl能正常访问目标服务,这大概率是因为目标服务仅监听IPv6地址,而你的代码只使用了IPv4协议栈进行连接。
可能的原因
- Docker容器内的DNS解析可能同时返回IPv4和IPv6地址,但
curl会自动尝试所有解析到的地址(优先IPv6或IPv4取决于系统配置),而你的代码仅限定IPv4(socket.AF_INET)连接。 - 目标服务(memaapp)的监听配置可能仅绑定了IPv6地址(比如
::),而非IPv4的0.0.0.0,导致IPv4连接请求被直接拒绝。
低栈层面的修复方案
修改代码,让它同时支持IPv4和IPv6连接,通过socket.getaddrinfo获取目标主机的所有可用地址,逐个尝试连接:
import socket import time def check_port_with_timing(hostname, port): """ Checks if a port on a given hostname is listening and measures the time taken to check. Parameters: - hostname: A string, the hostname or IP address to check. - port: An integer, the port number to check. Returns: - A tuple containing a boolean indicating if the port is listening and the time taken in milliseconds. """ start_time = time.time() try: # 获取目标主机所有可用的地址信息(包含IPv4和IPv6) addrinfo_list = socket.getaddrinfo(hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM) for addrinfo in addrinfo_list: af, socktype, proto, _, sockaddr = addrinfo with socket.socket(af, socktype, proto) as sock: sock.settimeout(5) try: result = sock.connect_ex(sockaddr) if result == 0: time_taken = (time.time() - start_time) * 1000 return True, time_taken except Exception: # 当前地址连接失败,尝试下一个 continue except Exception as e: print(f"DNS解析或地址获取出错: {e}") time_taken = (time.time() - start_time) * 1000 return False, time_taken
额外验证步骤
- 在mematest容器内执行
ss -tulpn查看memaapp的监听地址,确认是否包含IPv4的0.0.0.0:4200,还是仅存在IPv6的:::4200。 - 可以直接传入memaapp的IPv6地址(格式如
[::1])测试代码,验证是否能连接成功,进一步确认问题根源。
内容的提问来源于stack exchange,提问作者Robert Alexander
相关产品推荐
相关产品推荐

