Debugging Tomcat in Docker container
Asked Answered
F

8

32

I have a CoreOS running in Vagrant. Vagrant private network IP is 192.168.111.1. Inside a CoreOS is a docker container with Tomcat 8.0.32. Pretty much everything works ok (app deployment etc.) just debugging does not. Tomcat is mapped to 8080 port and the JPDA port should be 8000.

Facts

Tomcat JPDA is configured with:

JDPA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000

It starts with catalina.sh jpda start command. The output in the console when running it with docker-compose is:

tomcat | Listening for transport dt_socket at address: 8000

From the container info I assume that ports are mapped as they should:

CONTAINER ID        IMAGE       COMMAND      CREATED             STATUS              PORTS                                            NAMES
dcae1e0148f8        tomcat      "/run.sh"    8 minutes ago       Up 8 minutes        0.0.0.0:8000->8000/tcp, 0.0.0.0:8080->8080/tcp   tomcat

My docker image is based on this Dockerfile.

Problem

When trying to run Remote debug configuration (screenshot below) I get the error Error running Debug: Unable to open debugger port (192.168.111.1:8000): java.net.ConnectException "Connection refused". I've tried everything from changing various configuration but no luck. Am I missing something?

enter image description here

Frierson answered 23/2, 2016 at 17:20 Comment(0)
C
40

This is the command I use for this:

docker run -it --rm \
  -e JPDA_ADDRESS=8000 \
  -e JPDA_TRANSPORT=dt_socket \
  -p 8888:8080 \
  -p 9000:8000 \
  -v D:/tc/conf/tomcat-users.xml:/usr/local/tomcat/conf/tomcat-users.xml \
  tomcat:8.0 \
  /usr/local/tomcat/bin/catalina.sh jpda run

Explanation

  • -e JPDA_ADDRESS=8000
    debugging port in container, passed as environment variable
  • -e JPDA_TRANSPORT=dt_socket
    transport type for debugging as socket, passed as environment variable
  • -p 8888:8080
    expose tomcat port 8080 on host as port 8888
  • -p 9000:8000
    expose java debugging port 8000 on host as port 9000
  • -v {host-file}:{container-file}
    overwrite tomcat-user.xml with my local on, since I need access to the manager api
    omit this line if this isn't necessary for your use case
  • tomcat:8.0
    see https://hub.docker.com/_/tomcat/
  • /usr/local/tomcat/bin/catalina.sh jpda run
    command to run in the container
Containment answered 20/11, 2016 at 14:52 Comment(3)
Setting JPDA_ADDRESS is crucial for making this work in docker. Tomcat defaults to binding against localhost instead of 0.0.0.0 so the debug port cannot be exposed.Cost
@tstevens, yes, yes, yes. Very helpful. To be more specific: -e JPDA_ADDRESS=0.0.0.0:8000Rocha
For JDK 9+, see the answer below: https://mcmap.net/q/446927/-debugging-tomcat-in-docker-container. You need JPDA_ADDRESS=*:<PORT>.Forked
P
20

The accepted answer didn't work for me, apparently because I was using Java 11. It seems that if you're using Java 9 or newer, you need to specify the JPDA address like this:

JPDA_ADDRESS=*:8100

Without that *, Tomcat listens only on 127.0.0.1.

See also the "Debugging" section in the official Tomcat 8 migration guide.

Provenience answered 18/4, 2019 at 11:39 Comment(1)
Thanks, caught this bug with: openjdk:8u131-jre-alpineUnderneath
T
10

You can always update the Dockerfile to something like the following: -

FROM tomcat:8-jre8
MAINTAINER me

ADD target/app.war /usr/local/tomcat/webapps/app.war

ENV JPDA_ADDRESS="8000"
ENV JPDA_TRANSPORT="dt_socket"

EXPOSE 8080 8000
ENTRYPOINT ["catalina.sh", "jpda", "run"]

This does mean though that your docker file has debug on by default which is probably not suited to a production environment.

Tropic answered 25/11, 2016 at 12:0 Comment(0)
M
4

Try add to your Dockerfile

ENV JPDA_ADDRESS=8000
ENV JPDA_TRANSPORT=dt_socket

It works for me

Murmansk answered 11/7, 2016 at 19:22 Comment(0)
C
1

You need to make sure that port 8080 is exposed to IntelliJ for connection. That is while running docker you shall require something like docker run -p 8080:8080

For example, I am able to achieve the similar requirement like this by doing below mentioned steps/checks.

This is what my docker run command looks like:

sudo docker run --privileged=true -d -p 63375:63375 -p 63372:8080 -v /tmp/:/usr/local/tomcat/webapps/config <container name>:<tag>

NOTE: I am exposing an extra port 63375 on container and on my host both. The same port I am using in CATALINA_OPTS below.

This is what my entry point (for the image that I am building) looks like. NOTE: I am using CATALINA_OPTS. Also, I am using maven to create image so below is excrept from pom.xml.

<entryPoint>
    <shell>cd /usr/local/tomcat/bin; CATALINA_OPTS="-agentlib:jdwp=transport=dt_socket,address=63375,server=y,suspend=n" catalina.sh run</shell>
</entryPoint>
Colver answered 3/3, 2016 at 11:50 Comment(8)
In the Facts section is container info that indicates that the tomcat ports are exposed correctly. Using lsof command i've checked that the port 8000 was free. I believe that the JPDA_OPTS are also configured correctly as the log is suggesting. Thanks for trying anyway.Frierson
What was the docker command you used to run the container ? That is important here. I am not sure when you are saying port was free, do you mean it was open and listening ? Also, where it was free/open - inside container OR on the host (where you are probably running the intellij) which is running the container ?Colver
Free/open port on the host: to make sure that no other app is taking it. Tomcat container runs with docker-compose (along with other containers). Ports are exposed in the docker-compose file. Run command is default (from the image catalina.sh jpda run).Frierson
I meant docker run command specially -p <hostPort>:<containerPort> part.Colver
I use docker-compose, therefore, there is no docker run command in my case. However, docker-compose port and docker run -p are the same thing (8000:8000 and 8080:8080).Frierson
Ahhh.. I see. I am unaware about the compose. But the exception that intellij is telling is indicator of port mapping only.Colver
There must be something else. Otherwise I would not be able to deploy the app to the server through 8080 port.Frierson
firewall iptables ?? just guessingColver
C
1

I resolved a similar, if not the same, issue when using docker-compose.

It involved the environment variables not being passed properly from the docker-compose.yml file.

See my stack overflow issue:

Clot answered 29/7, 2017 at 0:48 Comment(0)
H
1

For me, it's cleaner this way:

docker run -e JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n" -p 8000:8000 tomcat:8.5-jdk8

This way, you don't have to modify your container Dockerfile.

Explanation: all java versions check the JAVA_TOOL_OPTIONS environment variable: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/envvars002.html

Hartung answered 24/6, 2019 at 7:43 Comment(0)
I
0

I have similar setup in my local environment. I included JPDA_ADDRESS as environment variable in the Dockerfile and recreated the containers.

ENV JPDA_ADDRESS 8000

#Expose port 8080, JMX port 13333 & Debug port 8000
EXPOSE 8080 13333 8000

CMD ["tail", "-f", "/dev/null"]  
Interglacial answered 3/5, 2017 at 2:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.