Remote debugging Java 9 in a docker container from IntelliJ IDEA - java

I have a Dockerfile with this content:
FROM openjdk:9
WORKDIR /project
ADD . /project
EXPOSE 5005
My docker-compose.yml looks like this:
version: "3.2"
services:
some-project:
build: .
ports:
- target: 5005
published: 5005
protocol: tcp
mode: host
command: "java '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005' SomeClass"
When I do docker-composer up I see a message "Listening for transport dt_socket at address: 5005". But when I try to connect with jdb or Idea I get "java.io.IOException: handshake failed - connection prematurally closed".
Everything works fine if I change openjdk:9 to openjdk:8. However, I need Java 9 for my project.

From Java 9, the JDWP socket connector accept only local connections by default. See:
http://www.oracle.com/technetwork/java/javase/9-notes-3745703.html#JDK-8041435
So, to enable debug connections from outside, specify *:<port> as address:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

Related

Connect Java Mission Control to Flink App in Docker

I'm trying to expose JMX in several docker-based Flink task managers using the --scale option of docker-compose for use with Java Mission Control. (e.g. docker-compose docker/flink-job-cluster.yml up -d --scale taskmanager=2)
My basic issue is that even though I have configured jmx with,
env.java.opts: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.host='0.0.0.0' -Djava.rmi.server.hostname='0.0.0.0'
env.java.opts.jobmanager: -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.rmi.port=9999
env.java.opts.taskmanager: -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.rmi.port=9999
Source: https://github.com/aedenj/apache-flink-kotlin-starter/blob/multiple-schemas/conf/flink/flink-conf.yaml
And then map the ports in the docker-compose file like so,
...
jobmanager:
image: flink:1.14.3-scala_2.11-java11
hostname: jobmanager
ports:
- "8081:8081" # Flink Web UI
- "9999:9999" # JMX Remote Port
command: "standalone-job"
....
taskmanager:
image: flink:1.14.3-scala_2.11-java11
depends_on:
- jobmanager
command: "taskmanager.sh start-foreground"
ports:
- "10000-10005:9999" # JMX Remote Port
environment:
- JOB_MANAGER_RPC_ADDRESS=jobmanager
.....
Source: https://github.com/aedenj/apache-flink-kotlin-starter/blob/multiple-schemas/docker/flink-job-cluster.yml
I am unable to connect Java Mission Control to the task managers using any of the ports. e.g. localhost:10000 or localhost:10001 etc. However I can connect to the Job Mangers using localhost:9999 And I can only connect to a task manager if I explicitly set the ports separately. Not using the dynamic port mapping in the docker-compose file. Ideally the the port mapping would work so I may continue to use the --scale command of docker-compose.

Spring boot client doesn't register to Spring admin on docker

Hello to all developers.
I have a problem and I have been struggling with it for a few days but I can not solve it.
The problem is I have two dockerized Spring application, one of them is admin and another is client. When I run these two out of Docker, the client registers with the admin without any problem, and I can see the client from the admin dashboard. But when I try to run these two as two containers in Docker with a Docker network, the client application gives this error:
de.codecentric.boot.admin.client.registration.DefaultApplicationRegistrator: Failed to register application as Application(name=spring client, managementUrl=http://545ade59e8dc:8585/actuator, healthUrl=http://545ade59e8dc:8585/actuator/health, serviceUrl=http://545ade59e8dc:8585/) at spring-boot-admin ([http://localhost:8080/instances]): I/O error on POST request for "http://localhost:8080/instances": Connection refused; nested exception is java.net.ConnectException: Connection refused. Further attempts are logged on DEBUG level
The admin application's docker-compose.yml file:
version: '3.3'
networks:
spring-admin-network:
driver: bridge
services:
spring-admin:
build:
context: .
args:
JAR_FILE: "./target/spring-admin-1.0.0.jar"
image: spring-admin
container_name: spring-admin
ports:
- "127.0.0.1:8080:8585"
networks:
- spring-admin-network
And the client application's docker-compose.yml file:
version: '3.3'
networks:
spring-admin-network:
driver: bridge
services:
repo-reporter:
build:
context: .
args:
JAR_FILE: "./target/spring-client-1.0.0.jar"
image: spring-client
container_name: spring-client
ports:
- "127.0.0.1:8081:8585"
networks:
- spring-admin-network
And application.properies for admin application:
spring.application.name=spring-admin
server.port=8585
spring.security.user.name=admin
spring.security.user.password=admin
And application.properies for client application:
spring.application.name=spring-client
server.port=8585
server.compression.enabled=true
server.http2.enabled=true
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
spring.boot.admin.client.url=http://localhost:8080
spring.boot.admin.client.username=admin
spring.boot.admin.client.password=admin
spring.boot.admin.client.instance.metadata.user.name=${spring.security.user.name}
spring.boot.admin.client.instance.metadata.user.password=${spring.security.user.password}
The commands I execute:
docker network create spring-admin-network
...Some hash...
cd /spring-admin
docker-compose build
...Successfully built...
docker-compose up -d
...Creating network "springadmin_spring-admin-network" with driver "bridge"
Creating spring-admin ... done...
cd ../spring-client
docker-compose build
...Successfully built...
docker-compose up -d
...Creating network "springclient_spring-admin-network" with driver "bridge"
Creating spring-client ... done...
docker logs -f spring-client
.
.
.
de.codecentric.boot.admin.client.registration.DefaultApplicationRegistrator: Failed to register application as Application(name=spring client, managementUrl=http://545ade59e8dc:8585/actuator, healthUrl=http://545ade59e8dc:8585/actuator/health, serviceUrl=http://545ade59e8dc:8585/) at spring-boot-admin ([http://localhost:8080/instances]): I/O error on POST request for "http://localhost:8080/instances": Connection refused; nested exception is java.net.ConnectException: Connection refused. Further attempts are logged on DEBUG level
Thanks in advance.
Docker creates a new docker network when you build and run the docker-compose file. as an example
xxx_spring-admin-network (for admin application)
yyy_spring-admin-network (for client application)
you can check by
docker network ls
First and foremost, you should set up a Docker network.
docker network create spring-admin-network
then make a docker-compose.yml change Both files should point to an existent network.
version: '3.3'
networks:
spring-admin-network:
external: true
...

Postgres container connection refused

Docker-compose with 2 containers. 1st is a Postgres database and 2nd is a Java Spring Boot application. For running, I use further docker-compose config file:
docker-compose.yml
version: "3.7"
services:
db-service:
image: postgres
restart: always
volumes:
- /home/ec2-user/dbdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: 1
POSTGRES_DB: auth
ports:
- 5432:5432
auth-service:
build: .
restart: always
depends_on:
- db-service
links:
- db-service
ports:
- 80:80
I suppose to use /home/ec2-user/dbdata to containing database data and after all, data is created. successfully. And log of postgres container is:
PostgreSQL init process complete; ready for start
2021-01-07 01:36:16.786 UTC
[1] LOG: starting PostgreSQL 13.1 (Debian 13.1-1.pgdg100+1) on
x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
2021-01-07 01:36:16.786 UTC [1] LOG: listening on
IPv4 address "0.0.0.0", port 5432 2021-01-07
01:36:16.786 UTC [1] LOG: listening on IPv6 address "::", port 5432
2021-01-07 01:36:16.790 UTC [1] LOG: listening on
Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2021-01-07 01:36:16.795 UTC [76] LOG: database system was shut down
at 2021-01-07 01:36:16 UTC 2021-01-07 01:36:16.800
UTC [1] LOG: database system is ready to accept connections
But Java app throws an error:
org.postgresql.util.PSQLException: Connection to 127.0.0.1:5432
refused. Check that the hostname and port are correct and that the
postmaster is accepting TCP/IP connections.
But in port mapping is 5432:5432.
And data source properties into Java app is:
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/auth
spring.datasource.username=postgres
spring.datasource.password=1
What is can be the reason for this error?
It's not working because the java app is pointed to 127.0.0.1 which is local to the java container and postgres is not running in that container.
In your properties file change this line:
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/auth
to
spring.datasource.url=jdbc:postgresql://db-service:5432/auth
Using db-service as the host comes from the name of the service in your docker-compose.yml file. See the docker compose networking page for more information.
Another option, since both containers are linked (as per docker-compose file) is to use localhost (instead of 127.0.0.1) as the DB host in the connection string -> spring.datasource.url=jdbc:postgresql://localhost:5432/auth

Remote debug ec2 java instance

My application is running in EC2 as a docker with java application.
I'm exposing 5005 port for debug, and locally it works perfectly. However on EC2 environment I get
java.net.ConnectException "Connection refused (Connection refused)"
when trying to connect using Intelij.
Security group is set to open ports 80, 5005, 22
Docker is exposing port 80 and 5005
Application is running with java args
-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=5005,suspend=n
Am I missing something ?
For those who are still interested, here is a way how to create a Remote JVM Debug on EC2 with docker
On the yaml file add the 'port' attribute.
ports:
- "5005:5005"
To the dockerfile run the Jar with the following command
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
On the inbound role on the EC2:
Cutsom TCP => 5005 => Your IP
In the Intellij create Remote JVM debug
In the host enter the host ip
Port: 5005
Choose JDK 9 or later as the address should be with *:5005
Click the Debug Button and it should work

Trouble running UPNP on Docker

I trying to run an UPnP service on my docker container using the Cling UPNP library (http://4thline.org/projects/cling/). There is a simple program that creates a device (in software) that hosts some service. This is written in Java and when I try to run the program I get the following exception (Note: This runs perfectly fine directly on my Ubuntu machine):
Jun 5, 2015 1:47:24 AM org.teleal.cling.UpnpServiceImpl <init>
INFO: >>> Starting UPnP service...
Jun 5, 2015 1:47:24 AM org.teleal.cling.UpnpServiceImpl <init>
INFO: Using configuration: org.teleal.cling.DefaultUpnpServiceConfiguration
Jun 5, 2015 1:47:24 AM org.teleal.cling.transport.RouterImpl <init>
INFO: Creating Router: org.teleal.cling.transport.RouterImpl
Exception occured: org.teleal.cling.transport.spi.InitializationException: Could not discover any bindable network interfaces and/or addresses
org.teleal.cling.transport.spi.InitializationException: **Could not discover any bindable network interfaces and/or addresses
at org.teleal.cling.transport.impl.NetworkAddressFactoryImpl.<init>(NetworkAddressFactoryImpl.java:99)**
For anyone that finds this and needs the answer.
Your container is obscuring your external network. In other words, by default containers are isolated and cannot see the outer network which is of course required in order to open the ports in your IGD.
You can run your container as a "host" to make it non isolated, simply add --network host to your container creation command.
Example (taken from https://docs.docker.com/network/network-tutorial-host/#procedure):
docker run --rm -d --network host --name my_nginx nginx
I have tested this using docker-compose.yml which looks a bit different:
version: "3.4"
services:
upnp:
container_name: upnp
restart: on-failure:10
network_mode: host # works while the container runs
build:
context: .
network: host # works during the build if needed
version 3.4 is very important and the network: host will not work otherwise!
My upnp container Dockerfile looks like so:
FROM alpine:latest
RUN apk update
RUN apk add bash
RUN apk add miniupnpc
RUN mkdir /scripts
WORKDIR /scripts
COPY update_upnp .
RUN chmod a+x ./update_upnp
# cron to update each UPnP entries every 10 minutes
RUN echo -e "*/10\t*\t*\t*\t*\tbash /scripts/update_upnp 8080 TCP" >> /etc/crontabs/root
CMD ["crond", "-f"]
# on start, open needed ports
ENTRYPOINT bash update_upnp 80 TCP && bash update_upnp 8080 TCP
update_upnp script is simply using upnpc (installed as miniupnpc in the Dockerfile above) to open the ports.
Hopefully this will help somebody.
Edit: Here is how update_upnp script may look like:
#!/bin/bash
port=$1
protocol=$2
echo "Updating UPnP entry with port [$port] and protocol [$protocol]"
gateway=$(ip route | head -1 | awk '{print $3}')
echo "Detected gateway is [$gateway]"
# port - e.g. 80
# protocol - TCP or UDP
upnpc -e 'your-app-name' -r $port $protocol
echo "Done updating UPnP entry with port [$port] and protocol [$protocol]"

Categories

Resources