Docker Compose中调试Gradle应用遇连接重置问题排查
问题现象
使用jdb -attach localhost:5005连接Docker内的Gradle Spring Boot应用时,出现连接重置错误:
java.net.SocketException: Connection reset at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:318) at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346) at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796) at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099) at jdk.jdi/com.sun.tools.jdi.SocketTransportService.handshake(SocketTransportService.java:133) at jdk.jdi/com.sun.tools.jdi.SocketTransportService.attach(SocketTransportService.java:273) at jdk.jdi/com.sun.tools.jdi.GenericAttachingConnector.attach(GenericAttachingConnector.java:119) at jdk.jdi/com.sun.tools.jdi.SocketAttachingConnector.attach(SocketAttachingConnector.java:83) at jdk.jdi/com.sun.tools.example.debug.tty.VMConnection.attachTarget(VMConnection.java:563) at jdk.jdi/com.sun.tools.example.debug.tty.VMConnection.open(VMConnection.java:369) at jdk.jdi/com.sun.tools.example.debug.tty.Env.init(Env.java:63) at jdk.jdi/com.sun.tools.example.debug.tty.TTY.main(TTY.java:1176) Fatal error: Unable to attach to target VM.
容器日志显示应用已在等待调试连接:Listening for transport dt_socket at address: 5005,且已完成5005端口的Docker映射。
核心原因及解决方案
1. 调试端口仅绑定容器本地回环地址
默认情况下,--debug-jvm参数会让JVM仅监听容器内的127.0.0.1:5005,而宿主机的localhost与容器的localhost并非同一网络空间,导致端口映射后无法连通。
解决方法:强制JVM监听容器的所有网卡地址(0.0.0.0),有两种实现方式:
方式一:修改Dockerfile的启动命令
调整development阶段的CMD,显式指定调试参数:
FROM gradle:8.1.1-jdk17 AS base COPY --chown=gradle:gradle . /home/gradle/src WORKDIR /home/gradle/src FROM base AS development EXPOSE 5005 CMD ["./gradlew", "bootRun", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005'"] # 其余阶段保持不变
方式二:在build.gradle中配置bootRun参数
在项目的build.gradle(或build.gradle.kts)中添加调试参数配置:
bootRun { jvmArgs = ['-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005'] }
修改后重启容器,日志会显示Listening for transport dt_socket at address: *:5005,此时宿主机即可正常连接。
2. 本地端口被占用
检查宿主机的5005端口是否被其他进程占用:
# macOS/Linux lsof -i :5005 # Windows netstat -ano | findstr :5005
若端口被占用,可修改Docker Compose的端口映射(例如5006:5005),然后使用jdb -attach localhost:5006连接。
3. 卷挂载路径不一致
Docker Compose中配置的卷挂载- ./:/app与Dockerfile的工作目录/home/gradle/src不匹配,可能导致Gradle加载的项目文件异常。建议修改卷挂载路径:
version: '3.8' services: demo: build: context: . target: development ports: - "5005:5005" - "8080:8080" environment: - SERVER_PORT=8080 volumes: - ./:/home/gradle/src # 与Dockerfile的WORKDIR保持一致
4. 防火墙/安全组拦截
检查宿主机防火墙是否允许5005端口的入站连接,或者Docker的网络规则是否限制了端口访问。
验证步骤
- 应用上述修改后,重启容器:
docker-compose down && docker-compose up --build - 确认容器日志显示
Listening for transport dt_socket at address: *:5005 - 重新执行
jdb -attach localhost:5005,验证连接是否成功
内容的提问来源于stack exchange,提问作者leedsunited92

