is it possible to get the docker host IP inside the java program running in the docker container?
From my understanding that docket from it’s initial design is to isolate the host from containers. Although this is doable, such as passing in a env variable to the container at startup, it is not a good practice. Try to containerize everything, and use a network and network links instead. [Docker Compose maybe helpful]
If you really need to do so for whatever reason here is a link for reference
How to get the IP address of the docker host from inside a docker container
Related
We have a setup where a single pod is running inside a node in our machine.
In normal Java application when we use the java.net.InetAddress.getLocalHost().getHostAddress(), it would give the system hostAddress where the server is running. But if the same API is called in a java application running inside a Kubernetes pod it would give the hostAddress of pod. Please let me know how to get the hostAddress of the system where the kubernetes pod is running and not the pod hostAddress?
Edit: Do not want to add Kubernetes dependencies, so please suggest how to achieve it in Java without kubernetes APIs.
I've got an application running in tomcat 8.5 in a docker container. Java version is jdk 8. There is a properties file that the app uses that points to another running service. In this case, I have the service running on my host machine and the property is set to point to my localhost:
my.external.service.url=http://localhost:8080/my-api-service
When my tomcat app is also running on the host machine, this works fine. But when my app runs in the docker container, I get a 404 error when it tries to call this service.
I tried switching the URL to point to my machine name:
my.external.service.url=http://my.pc.url.com:8080/my-api-service
But in this case, even though it still works if the tomcat app is running on the host instead of the docker container, I get a different error:
java.net.UnknownHostException: my.pc.url.com: No address associated with hostname
How do I configure the container so that I can get this to work?
Looking at the specific error you got - No address associated with the hostname - that means it cannot resolve the hostname to an IP. So you can find you local host IP and then pass an argument to the docker run command to add that host to the container lookup. Eg: -add-host="my.pc.url.com:X.X.X.X"
Docker networking is a potentially complex thing. Basically, if you run two separate containers they will not 'see' each other. You could have them both expose ports on the host machine and have then 'connect' that way, but you are better using the networking features of docker to ensure the containers talk to each other.
For a simple example like you have - say just two containers running tomcats that you would like to talk to each other - you might be best to just run them both via docker-compose so that they are in the same network.
There are many resources on the internet to explain the further details of docker networking if you wish to explore.
I am working on a mac machine and installed the latest Kubernetes and followed the example here (this is for dev’t purpose). All went smooth but I was hoping that Kubernetes provide me an ip address and port number where my service will be listening to so that I can access it from anywhere.
Please correct me if I am wrong.
I was able to run ifconfig as well as curl $(minikube service hello-minikube --url) and I was able to see the ip address and port but I wasn’t able to access it outside command line where Kubernetes lives in.
The reason I am trying to access it outside the VM is because we have other projects that run on other machines and I wanted to call the REST service I installed while we are on dev env. This way we don’t have to wait until the service is pushed to production.
FYI: This is my first micro service project and I would appericiate your feedback.
I followed the steps in the article you linked and it works as expected.
Just do:
minikube service hello-minikube --url
You will get a url like http://192.168.99.100:32382/ - the port and IP could and will change for you. Also note that the exposed port will be a random port like the 32382 and not 8080 that the pod uses.
Use the url in your browser, say and you should be able to see the output of the service.
Consider this setup:
So there's a JMX Server and we want it to be reachable from different JMX Clients, but the problem is that these different JMX clients knows HostX by different names/addresses. For the sake of the example lets say that HostA knows HostX by the name of hostx but HostB knows HostX by the name of hostxshadow.
I'm looking for recommendations on how to solve this problem under the following scenarios:
Where I have control over the source code of the JMX Clients and JMX Server.
Where I have no control over the source code, i.e. I can set System Properties on the JVM, but that's it.
The basic problem to be solved is that in the RMI world the server-side decides how a client should connect (right?). So setting e.g. java.rmi.server.hostname on HostX isn't going to help. As I see it I can only make either HostA happy or HostB happy, but not both at the same time.
Is the conclusion really that any RMI Server can only work if all clients would use the same name to access it?
Your conclusion is correct. It's a design flaw in RMI. There is an underlying assumption that there is a single 'most public' hostname or IP address by which the server host can be contacted by everybody.
Your statement about the host embedding its own name or address in the stub is also correct.
RMI is one possible transport of JMX. Another solution is JMXMP and switching to it is very simple, check at http://meteatamel.wordpress.com/2012/02/13/jmx-rmi-vs-jmxmp/ or
http://blog.markfeeney.com/2010/10/jmx-through-ssh-tunnel.html.
The basic problem to be solved is that in the RMI world the server-side decides how a client should connect (right?). So setting e.g. java.rmi.server.hostname on HostX isn't going to help. As I see it I can only make either HostA happy or HostB happy, but not both at the same time.
This is not going to help you but for others, the trick to do is to set the java.rmi.server.hostname system property to a name that means something on HostA which is inside of the firewall but another thing to HostB which is outside.
For example, in EC2 land we set the hostname property to be the EC2 node's "public hostname" which we get by doing a:
wget -q -O - http://169.254.169.254/latest/meta-data/public-hostname
This resolves to be some like:
ec2-54-1-2-3.compute-1.amazonaws.com
On the box itself and any others that are inside of EC2 this resolves to be 10.1.2.3 while on the outside world it resolves to the externally facing IP 54.1.2.3. Amazon does this DNS work by default. You may need to adjust the /etc/hosts file as necessary to get the names to be correct.
For more details on EC2 and JMX, see: How to connect to Java instances running on EC2 using JMX
I have a lot of experience with jconsole.exe and JVisualVM.exe , in the JDK1.6 and have connected thousands of times from a Windows JVM over to a Windows JVM on another machine via JMX.remote but it fails when I try to monitor a java instance that is running on a Linux host (from a Windows host and I tried JMX listener on redhat and SUSE at Amazon EC2). I also tried using jconsole.exe and get a similar error.
Is there any reason anyone can think of , why this kind of JMX connection would have a problem. Any ideas I can try? Has anyone "actually" done this and can say it will work if I persevere?
The error I get from JVisualVM (on the remote connect attempt) is something like this:
"Cannot connect using service:jmx:rmi:///jndi/rmi://<jmx service ip>:8001/jmxrmi"
My remote JMX service config is like this:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8001
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.hostname=<jmx service ip>
Found a similar question at this link but it didn't answer my question.
I verified that "iptables" is not enabled as a service and is not on and so I don't imaging there is any sort of firewall blockage. Also, both the windows and linux machine are on a 10.0.0.0 private internal subnet together. I am able to telnet into the port 8001 to verify its there , and its listening (netstat -ap) on the linux machine.
See the system property java.rmi.server.hostname. On your Linux server JVM, set this system property to be the public IP of the host. Then use the public IP in you client JMX URL.
I think your problem is that the RMI implementation is kind of hard to work with through firewalls and such as it requires more than the port you specify to work. Things you typically wouldn't notice if you connect to your own machine or a machine on the same network.
This post describes the problems you will run into quite well
If I were you, I would try to setup jmxmp as an alternative protocol. To do so you need to add the jmxremote_optional.jar (free from Oracle, download "JMX Remote API 1.0.1_04 Reference Implementation" from here) to both the server and the jvisualvm classpath but it is worth it.
If you google for jmxmp you will find quite a few examples on how to set things up, one of my first hits are http://pub.admc.com/howtos/jmx/distributed-chapt.html#jmxmp-sect which may be a bit too code oriented but I add it here anyway because it explains the things like like most with jmxmp in a few good sentences.
How to define the server side endpoint is depending on what you are running. Most app servers will let you type in a jmxmp enabled jmx service url but if the server is written from scratch you might have to set it up yourself in code instead of using the -D switches to java you are used to.
Give it a try and return with more specific questions about it if you run into problems.
Edit:
After you have added the jar to the classpath, the only thing you have to do in your code (assuming you are not using a server app that already handles it for you) is the following (omitting declarations, exception handling and such as you will figure it out anyway):
url=new JMXServiceURL(jmxurl);
this.server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, ManagementFactory.getPlatformMBeanServer());
this.server.start();
Have you tried creating an SSH tunnel to the Linux box from your Windows machine? http://oldsite.precedence.co.uk/nc/putty.html
Or if you have cygwin, just try ssh -f your-user#remote-server.com -L 7777:remote-server.com:123 -N where 7777 is the port on YOUR windows machine, and 123 is the port on the remote Linux box that listens to JMX commands.
With either of the above, you can use jconsole or visualvm on your Windows box and connect to localhost:7777.
I know iptables is disabled, but just confirm that JMX is working fine at that port by SSHing into the Linux box and trying to use commandline JMX mode of jconsole for localhost (on the Linux box).
I have actually just tackled this problem myself and figured it out.
I would wager that the problem is the RMI connections - you can't predict which ports it will use and so you can't get it to work with a firewall.
The workaround is to use an SSH proxy:
SSH to the box where your application is running but use the -D option like this:
ssh user#remoteHost -D 9999
As you are on Windows, you can use Cygwin to run the command above, or you can do the same thing with Putty through the GUI (guide here: http://blog.ashurex.com/2012/03/15/creating-ssh-proxy-tunnel-putty/)
This will start a socks proxy on your local machine on port 9999.
Open JVisualVM and in the preferences, under 'network' configure it to use a socks proxy at localhost, on port 9999.
If you do the above, you should then be able to connect to the remote machine as normal and since all the RMI traffic is now going over the SSH proxy, it is punched through the firewall and works nicely.
Good luck :-)