Docker单容器内报Connection refused及无法分配请求地址错误
问题原因
出现该问题是三个配置不匹配共同导致的,和跨容器通信、容器宿主机通信规则无关:
- 冗余的端口映射配置引发冲突:你配置的
2947:2947端口映射仅用于把容器端口暴露给宿主机/外部网络,容器内部通信完全不需要该配置。该规则会让Docker在网络栈中生成端口代理条目,部分环境下会干扰容器内部进程对同端口的绑定操作。 - gpsfake默认监听逻辑和容器网络不兼容:
gpsfake启动内置gpsd进程时,默认会同时尝试绑定IPv6回环地址::1、所有网卡的IPv4地址。而Python slim基础镜像搭配默认Docker bridge网络(包括你手动创建的自定义bridge网络)默认未启用IPv6支持,lo回环接口不存在::1地址,进程尝试绑定不存在的IP时就会抛出cannot assign requested address错误。 - 缺少服务就绪等待逻辑:如果测试脚本启动gpsfake进程后立刻发起连接,此时服务还没完成端口监听,就会抛出
Connection refused错误。
修复步骤
按以下顺序调整配置即可:
- 精简docker-compose配置,删除完全用不上的端口映射、外部自定义网络配置(单容器场景不需要自定义网络,使用默认网络即可),修改后的配置参考:
version: '3.3' services: test: image: program-test
- 修改脚本中启动gpsfake的命令,强制限定其仅使用IPv4栈、仅监听本地回环地址,不要尝试绑定IPv6地址或其他网卡IP,启动命令示例:
gpsfake -4 -l 127.0.0.1 你的GPS模拟轨迹文件路径
参数说明:
-4:强制gpsd/gpsfake全程使用IPv4协议栈,禁止尝试绑定IPv6地址-l 127.0.0.1:强制服务仅监听lo回环地址,不对外暴露端口,完全匹配你的容器内通信需求
- 在测试脚本中增加端口就绪等待逻辑,启动gpsfake后不要立刻发起连接,循环检测127.0.0.1:2947端口可连通后再执行测试用例,参考实现:
import socket import time max_wait_seconds = 10 start_time = time.time() while time.time() - start_time < max_wait_seconds: try: with socket.create_connection(("127.0.0.1", 2947), timeout=1): break except (ConnectionRefusedError, socket.timeout): time.sleep(0.2) else: raise RuntimeError("gpsfake 服务启动超时,未在规定时间内监听2947端口")
调整完成后重新构建镜像、启动容器即可正常运行,不需要修改Dockerfile内容,也不需要调整Docker的全局网络配置。
内容的提问来源于stack exchange,提问作者Ciro García
相关产品推荐
相关产品推荐

