当调试器在 Mac 上作为服务器运行时,如何在 Docker 容器中调试 Java 应用程序
我想调试一个在 Docker 容器中运行的 Java 应用程序。 当 Java 应用程序是服务器而调试器是客户端时,我可以实现这一点。 对于我的用例,如果交换角色会更好,即 java应用程序是客户端,调试器是服务器。当我像这样运行它们时,出现“端口已绑定”异常,并且带有 java 应用程序的容器未启动。 发生这种情况是因为调试器启动(作为服务器)并且它获取端口,但是当 docker 容器启动时,我猜它也会尝试将侦听器附加到同一端口,因为我启动容器的方式存在端口转发/映射。尽管包装的 Java 应用程序充当客户端并且不需要此端口上的侦听器,但 Docker 尝试在此端口上注册侦听器,然后无法启动。我使用的Docker网络模式是“bridge”。如果我使用“主机”模式,可能不会出现此问题,但此模式在 Mac 上不可用(仅限 Linux)。我用的是Mac。
是否可以在 Mac 上实现这样的设置,即调试器作为服务器启动,Docker 容器中的 Java 应用程序作为客户端启动?
更新:
在 Docker 容器内运行的 java 应用程序以这种方式启动:
java -cp "./classes:./lib/*" -agentlib:jdwp=transport=dt_socket,server=n,suspend=n ,address=*:8050 com.EntryPointClass
java 应用程序的客户端/服务器行为(与调试有关)由上面的 agentlib 选项中的“server=n”部分设置。
容器本身是这样启动的:
docker run --name async_batch_job --network my_net -p 8050:8050 my_docker_image:latest
为什么我在调试时需要 Java 应用程序充当客户端:
我可以我设置为java(服务器)和调试器(客户端),它工作正常。这是调试 Java 应用程序的常用方法。 然而,在我的场景中,这个特定的容器作为异步后端任务启动。我无法为其附加调试器 提前,因为容器还不存在。我想将调试器作为服务器启动。它将开始侦听调试会话。 一旦容器启动,它将连接到调试器,然后即使断点是 Java 应用程序中的第一行代码,也可以停止/调试执行。 如果我在 agentlib 选项中设置“suspend=y”,我可以实现类似的行为。但缺点是容器执行会暂停,直到附加调试器。 当我想调试时,这很好,但是当我只想运行应用程序(不调试)时,我不想为附加调试器而烦恼,只是为了让容器完成其工作。 如果我交换角色 - java应用程序是客户端,调试器是服务器,那么它会更方便。我可以提前启动一个调试器,它会自动附加。如果我不想 debug 然后不会启动调试器,并且 java 应用程序仍将被执行。在连接调试器之前它不会暂停。
I want to debug a Java app which runs in a Docker container.
I can achieve this when the Java app is the server and the debugger is the client.
For my use case it would be better if the roles are swapped i.e.
the java app is the client and debugger is the server. When I run them like this I have "port already bound" exception and the container with the java app doesn't start.
This happens because the debugger starts (as server) and it gets the port however when the docker container starts I guess it also tries to attach a listener to the same port because there is port forwarding/mapping in the way I start the container. Even though the wrapped Java app acts as a client and it doesn't need a listener on this port it is Docker that tries to register a listener on this port and then it fails to start. The Docker network mode I use is "bridge". Probably I would not have this problem if I use "host" mode but this mode is not available on Mac (Linux only). I use Mac.
Is it possible to achieve such set up on Mac i.e. debugger started as server and Java app in Docker container started as client?
UPDATE:
The java app which is run inside a Docker container gets launched this way:
java -cp "./classes:./lib/*" -agentlib:jdwp=transport=dt_socket,server=n,suspend=n,address=*:8050 com.EntryPointClass
The client/server behavior of the java app (in regards to debugging) is set by the "server=n" part in the agentlib options above.
The container itself is started this way:
docker run --name async_batch_job --network my_net -p 8050:8050 my_docker_image:latest
Why I need the Java app to act as a client when debugging:
I can have my set up as java (server) and debugger (client) and it works fine. This is the usual way of debugging java apps.
However, in my scenarion this particular container gets launched as an async backend task. I can't attach a debugger to it
in advance because the container doesn't exist yet. I would like to start the debugger as a server. It will start listening for debug sessions.
Once the container gets started it will connect to the debugger and then the execution can be stopped/debugged even if the breakpoint is the very first line of code in the Java app.
I could achieve similar behavior if I set "suspend=y" in the agentlib options. The disadvantage though is that the containers execution is paused until a debugger attaches.
When I want to debug this is great but when I simply want to run the app (no debugging) I don't want to be bothered with attaching a debugger just to allow the container to do its job.
If I swap the roles - java app is client, debugger is server then it will be more convenient. I can start a debugger in advance and it will attach automatically. If I don't want to
debug then no debugger is started and the java app still will be executed. It won't pause until a debugger is attached.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我正在使用远程容器作为客户端和主机作为服务器上的 Mac 上的Java调试。
使用 docker桌面,将主机作为
host.docker.internal
而不是*
。因此,应将其
暂停在远程上,应为<代码> y 。
否则,调试代理将失败连接。
注意
看起来Docker Desktop已在主机
/etc/hosts
Note 上附加了一条线以“主机”为“主机”。
遥控器上的应用代码还应用
localhost
替换为host.docker.internal
。I am using java debugging on mac with remote container as client and host as server.
Using Docker Desktop, having host as
host.docker.internal
instead of*
is needed.Thus, it should be
Suspend on remote should be
y
.Otherwise, debugging agent will fail connection.
Note
Looks like Docker Desktop has appended a line to 'hosts' on the host machine
/etc/hosts
Note
Application code on the remote should also replace
localhost
with thehost.docker.internal
.