You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署SpringBoot通过localhost访问服务连接被拒问题排查

问题根因

核心差异是不同程序对localhost域名的解析逻辑不一致:

  1. cB服务配置的extra_hosts规则本质是修改容器内/etc/hosts文件,将localhost等域名指向宿主机网关IP。容器内用curl请求时,curl依赖系统glibc的域名解析逻辑,会优先读取/etc/hosts配置,因此能拿到宿主机IP,访问宿主机上映射的cA服务6601端口,表现为请求正常。
  2. OpenJDK 11环境中,JVM内置了对localhost域名的特殊硬编码解析逻辑:默认直接将localhost映射到本地回环地址(127.0.0.1/::1),不会读取/etc/hosts中配置的localhost覆盖记录。因此B应用内通过RestTemplate发起请求时,实际连接的是B容器自身回环接口的6601端口,但B容器内部没有任何进程监听6601端口,自然抛出连接拒绝异常。
  3. cA配置的6601:6601端口映射规则仅作用于宿主机网络,不会在cB容器的回环接口上开放6601端口,这也是JVM连本地6601失败的基础原因。
无代码修改的可行解决方案

以下方案均不需要修改B应用的硬编码地址,按稳定性从高到低排序:

  • 方案1:cB容器内部部署端口转发规则
    在cB容器启动时,先通过socat工具监听本地回环的6601端口,将流量转发到同compose网络下的cA服务6601端口,完全绕开域名解析逻辑。修改cB服务的docker-compose配置即可:
    1. 如果原有镜像没有socat,直接重写启动命令,先安装socat、启动转发规则,再启动Java应用:
    services:
      cB:
        # 原有其他配置(镜像、端口映射等)保持不变
        entrypoint: ["/bin/sh", "-c"]
        command:
          - apt update && apt install -y socat &&
            socat TCP-LISTEN:6601,bind=127.0.0.1,fork TCP:cA:6601 &
            java -jar 实际B应用jar包名称.jar
    
    该方案兼容性最强,不受宿主机操作系统、JVM解析逻辑影响,只要两个服务在同一个compose私有网络下就能正常通信。
  • 方案2:修改JVM启动参数强制读取系统hosts配置
    给B应用的java启动命令追加JVM参数,强制JVM使用系统域名解析规则,读取/etc/hosts中的配置,不再使用内置的localhost硬编码逻辑:
    services:
      cB:
        # 原有其他配置保持不变
        command: java -Djdk.net.hosts.file=/etc/hosts -jar 实际B应用jar包名称.jar
    
    该参数在部分小版本OpenJDK 11中存在兼容问题,如果启动后报参数错误,可以替换为-Dsun.net.spi.nameservice.provider.1=default参数实现相同效果。
  • 方案3:两个服务均使用host网络模式
    去掉cA、cB服务的端口映射配置,直接将两个服务的网络模式改为host,直接复用宿主机网络栈,此时两个应用访问localhost:6601就和非容器环境下表现完全一致:
    services:
      cA:
        # 原有配置去掉ports段
        network_mode: host
      cB:
        # 原有配置去掉ports段、extra_hosts段
        network_mode: host
    
    该方案仅适用于Linux宿主机,Windows、Mac环境下Docker Desktop对host网络的支持存在缺陷,不建议使用。
排查参考点
  • 容器内/etc/hosts配置的域名映射,仅对遵循操作系统标准解析流程的程序生效,部分运行时(如JVM、旧版本Go程序)会内置独立的域名解析逻辑,不受/etc/hosts修改影响。
  • Docker的端口映射规则是在宿主机的网桥上做DNAT转发,不会在其他关联容器的网络命名空间内开放对应端口,因此其他容器访问自身本地回环的对应端口时,无法命中宿主机上映射的服务。
  • 同docker-compose启动的服务默认会加入同一个私有网络,服务之间可以直接通过服务名作为域名互相访问,不需要配置端口映射到宿主机。

内容的提问来源于stack exchange,提问作者SMF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 13:06:21