Expose random port to docker-compose.yml - java

I need multiple instance of same application, for that I am using
server.port=0 to run application in random port.
my question is how can I map randomly generated port to docker-compose.yml to create multiple instances.
I am using spring boot at the back-end. I am unable to find any solution.
Any help much appreciated.

Each Docker container runs a single process in an isolated network namespace, so this isn't necessary. Pick a fixed port. For HTTP services, common port numbers include 80, 3000, 8000, and 8080, depending on permissions and the language runtime (80 requires elevated privileges, 3000 is Node's default, and so on). The exact port number doesn't matter.
You access the port from outside Docker space using a published port. If you're running multiple containers, there is the potential for conflict if multiple services use the same host port, which is probably what you're trying to avoid. In the docker run -p option or the Docker Compose ports: setting, it's possible to list only the port running inside the container, and Docker will choose a host port for you.
version: "3"
services:
web:
image: ...
ports:
- "8000" # no explicit host port
command: ... -Dserver.port=8000 # fixed container port
docker-compose port web 8000 will tell you what the host (public) port number is. For communication between containers in the same docker-compose.yml file, you can use the service name and the (fixed, known) internal port, http://web:8000.

Related

Java Spring Boot Random Port with Dockerfile

If you're using Java Spring Boot, you can set the server port the application runs on to any port, but also to a random port:
server:
port: 0
However, when I now use a Dockerfile for my application, I won't know what port to EXPOSE. Is there any way to find this port?
Don't use a random port for the Spring app. Use the default port and have Docker expose that as whatever port you like.
Don't use a random port for the Spring app. Specify it via an environment variable and have Docker provide that.
when you started an app, you can see at console I think. As I know docker use 8080 or 8081.
EDIT 1:
Check this -> link
You can expose a port through your Dockerfile or use --expose and then publish it with the -P flag. This will bind the exposed port to your Docker host on a random port (verified by running docker container ls).
You can expose a port through your Dockerfile or use --expose and then publish it with the -p 80:80 flag. This will bind the exposed port to your Docker host on port 80, and it expects the exposed port is 80 too (adjust as necessary with HOST:CONTAINER).
You can ignore exposing anything and just use -p 80:80 in which case this doubles as both exposing AND publishing the port.

Cannot connect jmx to java app running in docker on remote host

Assuming I have a server in my local network with ip 192.168.100.10.
There is docker container running in it with java application.
Now i want to connect to this java application with VisualVM from my computer which has ip address 192.168.100.20. I thought I had everything configured properly but it still does not work.
I have passed these JVM options:
-Dcom.sun.management.jmxremote"
-Dcom.sun.management.jmxremote.port=9010"
-Dcom.sun.management.jmxremote.authenticate=false"
-Dcom.sun.management.jmxremote.ssl=false"
-Dcom.sun.management.jmxremote.local.only=false"
-Dcom.sun.management.jmxremote.rmi.port=9010"
-Djava.rmi.server.hostname=192.168.100.10"
Then I have exposed port 9010 in Dockerfile:
EXPOSE 9010
Then added this port to docker-compose:
ports:
- "9010:9010"
I am trying to connect to remote host with JConsole or VisualVM from my local machine. In "Remote Process" input in JConsole I put "192.168.100.10:9010" but connection fails with error:
"The connection to 192.168.100.10:9010 did not succeed. Would you like to try again?"
What am I doing wrong?
The solution above is sufficient and working. I've been using env variable to set port number which was not working properly.

how to run a jar in amazon Ec2 and access it over the internet

I am fairly new to AWS Instances. I am able to install java in the EC2 instance and able to run my jar. but I am not able to access the jar from the internet. It's a rest service build using spring boot. It run's in tomcat port 8080. But I see the jar running in private mode where it can only be accessed from EC2 instance(from my understanding). But how can I run the jar in the EC2 instance where I can access it over the internet.
Add TCP port 8080 as inbound rule to your security group.
aws ec2 authorize-security-group-ingress \
--group-id $SECURITY_GROUP_ID \
--protocol tcp --port 8080 --cidr 0.0.0.0/0
See also: EC2: How to add port 8080 in security group?

Cannot produce message to kafka from service running in docker

I've a rest service running in docker container on port 5000 which is used to produce message over kafka topic running out of docker container.
I've configure my producer client with below properties :-
bootstrap.servers=localhost:9093
And I've started my contained with below command:-
docker run -d -p 127.0.0.1:5000:5000 <contained id>
I've also made below configuration to advertise kafka host and port
advertised.host.name=localhost
advertised.port=9093
Despite of having all configuration when I try to produce to a kafka topic then I get below error:-
org.apache.kafka.common.errors.TimeoutException: Failed to update metadata after 60000 ms.
Can someone please point where the actual problem is?
In real life, advertised.host.name should never be localhost.
In your case, you run your Docker container in bridge networking mode, so it won't be able to reach the broker via localhost, as it will point to the container network, not the host machine.
To make it work you should set the advertised.host.name and bootstrap.servers to the IP address returned by ifconfig docker0 (might be not docker0 in your case but you get the point).
Alternatively, you may probably run your container with --net=host, but I think you'd better properly configure the advertised host name.

Docker Container interacting with 2 applications

I currently have a Java Application (.jar) in one container and I am using the docker-compose.yml to create an instance of a mysql database in a second container.
I want to know if it is possible for the container 1 to be able to interect with container 2, and be able to read/write to and from the mysql database
If it is possible, how would I go about this?
Each container is like a virtual machine running inside your actual machine. And they have a virtual network that connects all of them. They can communicate with each other just like real machines on a real network.
When you specify links in your yaml, e.g. from the example from the documentation:
web:
links:
- db
The result will be that inside the web container, the hostname db will resolve to the virtual IP of the db container. You can actually do ping db from within the web container and you should see the db container answer.
For mysql, assuming you named the mysql container db like in the example and linked your application to it like above, you'll simply have to write code that assumes this hostname. E.g. you'd connect to jdbc:mysql://db:3306/databasename. The port depends on what the image you use exposes.
It gets tricky once you want to have the containers running on actually different machines because you need a way to reach the virtual container network inside those machines. There are ways like proxies, forwarded ports, overlay networks, .. but that's beyond the capabilities of compose.
From the code point of view, the interaction is the same.
Your MySQL in Docker exposes the service on a particular hostname and port. The program using it uses that hostname and port. Docker gives you the ability to configure this outside MySQL, but the Java code is the same.
Yes, linking containers over a network is standard functionality.
As Peter Lawrey mentioned, you just configure the database connection in Java as normal with the name of service or docker container you want to connect to.
version: "2"
services:
web:
image: myapp
networks:
- myapp
db:
image: mysql
networks:
- myapp
networks:
myapp:
driver: bridge
Then you have a network to connect over
$ docker-compose start
Starting composenetworks_web_1
Starting composenetworks_db_1
$ docker exec composenetworks_web_1 ping db
PING mysql (172.22.0.3): 56 data bytes
64 bytes from 172.22.0.3: seq=0 ttl=64 time=0.093 ms

Categories