I’ve got a Java Web (Jetty-based) app running in a container that I debug (see https://github.com/Unicon/ccc-shib-split-authn/).
Essentially you want to map a debug port from the Docker container to the Docker host. I used 5005. -p 5005:5005. Then you need to tell the Java process to use debugging: You can see how do it at https://github.com/Unicon/ccc-shib-split-authn/blob/master/src/test/docker-compose/idp/run-jetty.sh#L17.
In Tomcat, catalina.sh has a jpda parameter you can use to invoke debugging. It will tell you the port that it is listening on. You can map and connect to that.
As for rebuilding the image, keep in mind that under most circumstances you don’t rebuild the whole image if the Dockerfile is built correctly. Put your COPY command as far down the bottom of the file as possible and only it will have to re-run when rebuilding. For example, the project I referenced takes a few minutes to build the image the first time. Every other run it takes seconds to add in the newly compiled library. Even if adding in a new war (mine just overlays on top of an expanded war as that is how the base app is delivered), it will take a few seconds to do that if Docker is hosted locally.
I can’t really speak to the CI aspects other than you can write integration tests against the Docker container and Jenkin’s etc just thinks it running the gradle/maven/etc script.
(Sorry the Java project is fairly small but there is quite a bit of extra stuff to make the app work for my use case. You’ll see I use docker compose to spin up several servers (LDAP, Apache, etc) but it all to support my Java dev.)