'How to debug Java app in Docker container when debugger runs as server on Mac
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
