如何在Intellij Idea中调试JDK Docker容器?

3

我想要使用以下调试选项启动Docker容器,但启动失败:

Dockerfile:

# syntax=docker/dockerfile:1
FROM maven:3-eclipse-temurin-11 as dependencies
WORKDIR /opt/app
COPY .dockerdev/settings.xml .
COPY pom.xml .
COPY src src
ENTRYPOINT["mvn", "spring-boot:run"]

docker-compose.yml:

version: '3.7'
services:
  app:
    environment:
      - "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
    ports:
      - 8080:8080
      - 5005:5005
      

结果:

docker-compose up
Recreating my_app ... done
Attaching to my_app
app_1  | Picked up JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
app_1  | Listening for transport dt_socket at address: 5005
app_1  | [INFO] Scanning for projects...
app_1  | [INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ my_app ---
app_1  | [INFO] Using 'UTF-8' encoding to copy filtered resources.
app_1  | [INFO] Using 'UTF-8' encoding to copy filtered properties files.
app_1  | [INFO] Copying 3 resources
app_1  | [INFO] Copying 3 resources
app_1  | [INFO] 
app_1  | [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ my_app ---
app_1  | [INFO] Changes detected - recompiling the module!
app_1  | [INFO] 
app_1  | [INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ my_app ---
app_1  | [INFO] Using 'UTF-8' encoding to copy filtered resources.
app_1  | [INFO] Using 'UTF-8' encoding to copy filtered properties files.
app_1  | [INFO] Copying 3 resources
app_1  | [INFO] 
app_1  | [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ my_app ---
app_1  | [INFO] Changes detected - recompiling the module!
app_1  | [INFO] Compiling 5 source files to /opt/app/target/test-classes
app_1  | [INFO] 
app_1  | [INFO] <<< spring-boot-maven-plugin:2.6.7:run (default-cli) < test-compile @ my_app <<<
app_1  | [INFO] 
app_1  | [INFO] 
app_1  | [INFO] --- spring-boot-maven-plugin:2.6.7:run (default-cli) @ my_app ---
app_1  | [INFO] Attaching agents: []
app_1  | Picked up JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
app_1  | ERROR: transport error 202: bind failed: Address already in use
app_1  | ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
app_1  | JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [./src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c:735]
app_1  | [INFO] ------------------------------------------------------------------------
app_1  | [INFO] BUILD FAILURE
app_1  | [INFO] ------------------------------------------------------------------------
app_1  | [INFO] Total time:  3.000 s
app_1  | [INFO] Finished at: 2022-05-23T12:30:50Z
app_1  | [INFO] ------------------------------------------------------------------------
app_1  | [ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.6.7:run (default-cli) on project my_app: Application finished with exit code: 2 -> [Help 1]
app_1  | [ERROR] 
app_1  | [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
app_1  | [ERROR] Re-run Maven using the -X switch to enable full debug logging.
app_1  | [ERROR] 
app_1  | [ERROR] For more information about the errors and possible solutions, please read the following articles:
app_1  | [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
my_app exited with code 1

顺便提一句:端口5005当然在我的主机上没有运行/监听! 另外,如果我将端口更改为5006、5007等,错误始终是相同的。

那么为什么在执行“mvn spring-boot:run”命令时该端口被阻止了呢?


问题在于您正在传递 JAVA_TOOL_OPTIONS。这将被 Maven Spring Boot 使用。Maven 也会以这些选项运行,打开调试 Maven 的端口。然后,一个新的进程将在分支 JVM 中启动 Spring Boot,该进程还会选择这些设置并尝试重新连接。您应该在 ENTRYPOINT 中传递属性,并指定 -Drun.jvmArguments=<remote-debug-here> 以使 Spring Boot 正常工作(并确保 maven 也不会检测到这些设置)。 - M. Deinum
显然,您应该使用 spring-boot.run.jvmArguments,并且您还需要注意引号。 - M. Deinum
请参阅 https://docs.spring.io/spring-boot/docs/2.7.0/maven-plugin/reference/htmlsingle/#run.examples.debug...。jvmarguments 也需要用引号括起来,因此您可能需要在字符串中添加一些 \" - M. Deinum
不幸的是,ENTRYPOINT["mvn", "spring-boot:run", "-Dspring-boot.run.jvmArguments=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005\""] 没有任何区别。 - membersound
是的,我完全删除了 JAVA_TOOL_OPTIONS。抱歉,我的意思是没有任何区别,我的应用程序可以启动,但是 agentlib 似乎无法被识别。日志缺少任何 agentlib 信息,因此容器内缺少 5005。 - membersound
显示剩余4条评论
1个回答

5
你的解决方案问题在于启动了两个调试会话。一个是 maven 命令,另一个是 Spring Boot 的分离 JVM。因此错误无法通过更改端口解决,因为问题将仍然存在。
你需要做的是从 Docker Compose 文件中删除 JAVA_TOOL_OPTIONS,并将以下内容添加到入口点。
-Dspring-boot.run.jvmArguments=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

这样的话,它只会应用于Spring Boot插件,并且在在新的JVM中启动应用程序时会被考虑在内。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接