I have a Docker container based on opendjdk:8-slim with installed Tomcat 9 and I am debugging apps deployed there from my IDE (IntelliJ) - the IDE runs on Docker host. I run the Tomcat with the following configuration
CATALINA_OPTS="-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=49520 \
-Dcom.sun.management.jmxremote.rmi.port=49520 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.local.only=false \
-Djava.rmi.server.hostname=10.0.75.1 \
-agentlib:jdwp=transport=dt_socket,address=49540,suspend=n,server=y"
Everything works great - I can attach the IDE to the container. Also the following command works (executed from docker host) - it can connect to the process in the container (the port 49540 in the container is mapped to the port 49540 on the host):
docker-host$ telnet localhost 49540
Now I want to upgrade to Java 9. I changed the base image from openjdk:8-slim to openjdk:9-slim and I can't connect to the debugger port from the docker host. Also from IDE, I got SocketTimeoutException: Connection reset. However, from inside the container I am able to connect to the debugger via telnet.
I tried several images of Java 9 from openjdk repository and also from other repos, for example adenix/java, but unfortunately with the same result.
Finally I found a way how to make it work using information in the comment provided by Alan Bateman.
Instead of setting debug settings in CATALINA_OPTS (which worked with JDK 8 without problems), I set JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=*:49540,server=y,suspend=n" and run Tomcat with catalina.sh jpda run. The concrete IP address (for instance address=192.168.16.1:49540) still doesn't work for me, although the IP address is reachable from within the container.
I'm using in my docker-compose.yaml this environment variable to run in the Java 9 with Tomcat 9:
...
environment:
- "JPDA_ADDRESS=*:8000"
...
Before in Java 8 I was using:
...
environment:
- "JPDA_ADDRESS=8000"
...
Related
In the below example since I have many environment variables I cannot directly run ENTRYPOINT with java -jar command option. Instead I have used entrypoint.sh
Dockerfile
ENV JAVA_TOOL_OPTIONS -agentlib:jdwp=transport=dt_socket,address=9251,server=y,suspend=n
RUN ["chmod", "777", "entrypoint.sh"]
ENTRYPOINT ["bash","entrypoint.sh"]
EXPOSE 9251
entrypoint.sh
java $JVM_OPTS $JAVA_OPTS org.springframework.boot.loader.JarLauncher
docker-compose.yaml
version: '3.1'
services:
bus:
image: sample-image
network_mode: "host"
ports:
- 9251:9251
environment:
- DEBUG_PORT=9251
- JVM_OPTS=-Xms1G -Xmx5G -XX:MaxMetaspaceSize=512m -XX:+UseG1GC
In the below snapshot we can see when the service is started with debugging enabled
when running sudo netstat -tulpn | grep :9251 shows
The docker is running in a linux box which I am trying to connect from local windows machine. Also note that it is mandatory that I need to keep the network_mode as host.
Docker part:
Can you try to remove a host network mode? And check whether it works.
Alternatively I don't see a reason to use port forwarding here, these two configurations are kind of mutually exclusive.
From the documentation:
If you use the host network mode for a container, that container’s network stack is not isolated from the Docker host (the container shares the host’s networking namespace), and the container does not get its own IP-address allocated. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application is available on port 80 on the host’s IP address.
And then:
Note: Given that the container does not have its own IP-address when using host mode networking, port-mapping does not take effect, and the -p, --publish, -P, and --publish-all option are ignored
So bottom line you should not deal with port forwarding in the network-mode=host and just make sure that your port is available on the host machine.
Java part:
It looks like your "java" part is ok, however it has a nuance: depending on the actual java version the remote server options slightly change:
For example in java 11 you should use:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:9251
And in java 8:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=:9251
Note the "*" that has changed. So you should try that...
I'm trying to access the welcome page of Wildfly running on a Docker container in Windows 10 Pro. This is what I did:
Pulled the image:
docker pull jboss/wildfly
Run Wildfly container (this works fine, in the Wildfly log I can see it started correctly):
docker run -it -p 8080:8080 jboss/wildfly
Find the container ID:
docker ps
Inspect the IP address:
docker inspect -f "{{ .NetworkSettings.IPAddress }}" cac63ed21d78
The IP address is 172.17.0.2, in a browser I go to http://172.17.0.2:8080/ but the browser hangs and times out. What am I missing?
UPDATE
I also tried with 127.0.0.1:8080 and it's not working either
UPDATE2
Console log:
docker --version
#Docker version 19.03.1, build 74b1e89e8a
docker run hello-world
#Hello from Docker!
docker run --detach --publish 8080:80 --name webserver nginx
#Unable to find image 'nginx:latest' locally
#latest: Pulling from library/nginx
#8ec398bc0356: Pull complete
#465560073b6f: Pull complete
#f473f9fd0a8c: Pull complete
#Digest: sha256:b2d89d0a210398b4d1120b3e3a7672c16a4ba09c2c4a0395f18b9f7999b768f2
#Status: Downloaded newer image for nginx:latest
#c5cdb6de11240b5fe33bc424779721e1b44948797fd6ff389004d0766b71dd17
docker ps
#CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c5cdb6de1124
#nginx "nginx -g 'daemon of" 10 minutes ago Up 10 minutes 0.0.0.0:8080->80/tcp webserver
By default, when you create a container, it does not publish any of its ports to the outside world. Network 172.17.X.X is internal. If you need to bind IP address to host ip run docker container with -p flag, like that:
-p 8080:8080
Map TCP port 8080 in the container to port 8080 on the Docker host
From: https://docs.docker.com/docker-for-windows/networking/
Port forwarding works for localhost; --publish, -p, or -P all work. Ports exposed from Linux are forwarded to the host.
So it should be accessible from http://localhost:8080
If that doesn't work, then try the windows example
docker run -d -p 80:80 --name webserver nginx
Which should be accessible http://localhost:80
https://docs.docker.com/docker-for-windows/index#explore-the-application-and-run-examples
If even that fails try:
docker-machine ip default
And use http://[docker-machine-ip]:80
The key information is Docker container in Windows 10 Pro - this is very generic specification how your Docker on Windows works. There can be many options e.g. Docker for Windows with/without Linux containers, Docker toolbox, remote instance, ....
Generally Docker containers on Windows are running in some kind of virtual machine (Hyper-V, Virtualbox, ...), usually. So there is additional network layer, which may not be accessible directly from your Windows network namespace. But linked example runs on Linux machine, where this additional network layer doesn't exist. And that is a reason why copy/pasted Linux example doesn't work on Windows. So run container as usual and expose port 8080:
docker run -it -p 8080:8080 jboss/wildfly
But IP for access will be different and container IP can't be used, because that internal docker network is very likely not accessible from Windows. Rather try to use IP of your Windows OS. Eventually check documentation of used Docker on Windows solution and find which IP is used for exposed ports.
If you have advance windows/linux networking skills, then you may somehow route/forward port from container network namespace, through intermediate VM network layer to Windows network layer. But it can be pretty complicated.
I had a peer working on a windows system that faced the same issue. He put a lot of effort into it and just couldn't get anywhere. There's a lot of weird stuff that happens with Docker Desktop for windows it seems. We finally just installed the linux subsystem for windows and installed docker on there and it worked like a charm for him from then on. If you wish to stick to windows and you don't mind working on the linux subsystem, I suggest you go down that route. We went further than what Jan Garaj suggested and just found it to be a waste of time. Docker Desktop for Windows is meant to be a env where you completely work within it - using dev containers etc. Host-Container stuff is a pain with it.
I want to run a Java Spring application inside of a docker container and this application should be able to deploy sibling containers. When I run the Java application directly on my machine it works fine and can deploy containers, but as soon as I try to run the application inside a container it does not work any more (im using supervisord to run the mongodb and Java Spring app in one container and I know that thats not best practice). The container starts up fine, but crashes as soon as my application tries to connect to the docker deamon without any stacktraces from Java, just the error WARN received SIGTERM indicating exit request. The supervisord logs dont contain additional info.
I tried mounting the docker socket from the host (Windows 10 Pro with Docker Desktop, also tried Ubuntu Server 18.04) into the container using -v /var/run/docker.sock:/var/run/docker.sock.
I also tried to use --net="host".
Both did not work, although with the second one the container does not crash but produces a different error ({}->unix://localhost:80: Connection refused) visible in the log of my java application, which indicates that it cant even find the right address for the deamon.
I also activated "Expose deamon on tcp://localhost:2375 without TLS".
I also tried to set the DOCKER_HOST environment variable inside the container to default values such as "tcp://localhost:2375" or "/var/run/docker.sock".
Here is the code that I use to initialize the docker client.
DockerClient docker = DefaultDockerClient.fromEnv().build();
The DefaultDockerClient.fromEnv().build(); should create a docker client that uses the DOCKER_HOST environment variable to connect to the host or the default adress ("/var/run/docker.sock" on *NIX).
Here is my DOCKERFILE:
FROM openjdk:8-jre-alpine
ENV PACKAGES mongodb supervisor
VOLUME /opt/server
VOLUME /data/db
WORKDIR /opt/accservermanager
ADD supervisord.conf /etc/supervisor.conf
ADD accservermanager.jar /opt/accservermanager/accservermanager.jar
ADD application.properties /opt/accservermanager/application.properties
RUN apk update && \
apk add --update $PACKAGES --no-cache && \
rm -rf /var/cache/apk/*
EXPOSE 8000
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor.conf"]
And finally, my supervisord.conf
[supervisord]
user=root
stderr_logfile=/var/log/supervisord.err.log
stdout_logfile=/var/log/supervisord.out.log
loglevel=debug
[program:mongodb]
command=mongod --smallfiles
autostart=true
autorestart=true
stderr_logfile=/var/log/mongo.err.log
stdout_logfile=/var/log/mongo.out.log
[program:accservermanager]
directory=/opt/accservermanager/
command=java -jar accservermanager.jar
autostart=true
autorestart=true
stderr_logfile=/var/log/accservermanager.err.log
stdout_logfile=/var/log/accservermanager.out.log
Expected result: Application connects to the docker client from the host and is able to deploy/manage containers on the host
Actual result: Container crashes or outputs errors.
Turns out that there is a new version of spotify-docker that fixes my problem.
Updating from v8.15.1 to v8.15.2 solved my issue.
I have developed a small Java demo web app, using gradle, which I want to dockerize with WildFly. I have followed instructions from here.
The Dockerfile is:
FROM jboss/wildfly
MAINTAINER Me <me#qmail.com>
RUN /opt/jboss/wildfly/bin/add-user.sh admin Admin#70365 --silent
ADD build/libs/my-demo.war /opt/jboss/wildfly/standalone/deployments/
When I start the image with Docker and browse localhost:8080 or localhost:9990, I get a This site can’t be reached.
Yet, my application runs successfully on localhost:8080 when I use gradle appRun.
What is missing?
I am under Windows 10 Home Edition. I have tried on another laptop under Ubuntu 16 and face the same issue.
Three things:
1st
the base image EXPOSEs only port 8080, so to be able to access port 9990 you need to add EXPOSE 9990 to your Dockerfile or --expose 9990 to your docker runcall.
2nd
You didn't post your cmd line call, so I can only guess but you need to map the container port to a host port, example (including the additional exposed port)
docker run --expose 9990 -p 9990:9990 -p 8080:8080 -it my-demo
3rd
If your working with docker-machine as it is still the case with Win 10 home as far as I recall, you won't have your application on localhost but at the IP of the docker-machine VM. You can find out which IP that is by calling
docker-machine ip
On linux you will have your app on localhost:PORT once you add the port mapping.
I am running Tomcat 6 on a Linux server in Amazon's cloud. I am trying to connect to it with VisualVM from my Mac at my office. I have allowed opened up all TCP ports between my desktop and the server, but I am unable to get VisualVM to do anything.
On the linux box, I have started Tomcat with:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9191
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
On my Mac, I launch VisualVM and choose File -> New JMX Connection...
I enter amazonhostname.com:9191 in the box. It says "Adding amazonhostname.com:9191..." and sits there for several minutes before timing out.
From my Mac, I can "telnet amazonhostname.com 9191" just fine, and I tried some other random ports, and they all worked. I'm pretty convinced it's not a firewall issue, unless I need to open UDP or ICMP or something like that. (Really??)
There is nothing in catalina.log on the server, or the system console on my Mac, related to jmx. netstat on the server shows 9191 and some other ports open on all interfaces.
There is no jstatd on the remote server. Is that a pre-requisite for JMX? (I am totally new to Java and I'm not even sure what those things mean, but I saw it on a blog post somewhere. I'm grasping at straws now.)
Set the hostname property before the VM starts:
java -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=9191 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=the.public.ip \
-jar program.jar
Add the relevant rules to your security group.
What worked well for me in RHEL7 environment is to implement the JmxRemoteLifecycleListener on Tomcat using the example provided in the documentation. I have also opened up ports 10001 and 10002 on the firewall.
JMX Remote Lifecycle Listener