DB driver is not found when running in docker swarm - java

I have a Spring boot application running with maven. I can successfully run my app locally, but when I run an image in the local docker swarm: docker stack deploy --compose-file docker-compose.yml compose I get the following error: Caused by: java.lang.IllegalStateException: Cannot load driver class: org.postgresql.Driver
I've checked env.getPropertySources():
compose_service#debian| spring.datasource.driver-class-name=org.postgresql.Driver
compose_service#debian| spring.datasource.url=jdbc:postgresql://localhost:5432/service
compose_service#debian| spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
These props work fine with local running.
I've checked, the built jar contains the Postgres lib; maven dependency in my project:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.1</version>
</dependency>
I recently ran the app with docker-compose up and it also worked, so it seems like a problem with running in swarm. Any ideas?

I shouldn't add secrets to docker swarm by echo,
which adds \n to each string (that's why my driver name wasn't valid).
Instead, I should use printf:
printf "org.postgresql.Driver" | docker secret create db-driver -
Hope it will save time for someone

Related

Jenkins build and deployment of spring boot client microservice fails because of config-server at https://localhost:8888 not present on maven build

My goal is to deploy 1 spring-config-server application AND 1 spring-boot-client application to the same Linux server machine.
spring-boot-client application port is 8081
spring-config-server application port is 8888
In Jenkins I created 2 jobs. First job is to build and deploy the spring-config-server application and start the jar. Second job is is to build and deploy the spring-boot-client application and start the jar.
I was able to build and deploy the spring-config-server application to the Linux machine. I can see it running at localhost:8888
Problem : Build task/job for spring-boot-client application in Jenkins is failing because when maven clean install is run, I believe that it tries to locate presence of a config server running at localhost:8888. I don't know if it's because of actuator dependency I added.
In Jenkins build console, this is what I get
Caused by: org.springframework.web.client.ResourceAccessException: I/O
error on GET request for "http://localhost:8888/application/dev":
Connection refused (Connection refused); nested exception is
java.net.ConnectException: Connection refused (Connection refused) at
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785)
at
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711)
at
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602)
at
org.springframework.cloud.config.client.ConfigServerConfigDataLoader.getRemoteEnvironment(ConfigServerConfigDataLoader.java:303)
at
org.springframework.cloud.config.client.ConfigServerConfigDataLoader.doLoad(ConfigServerConfigDataLoader.java:118)
... 94 common frames omitted Caused by: java.net.ConnectException:
Connection refused (Connection refused)
In the spring-boot-client app's application.properties, the only setting I have are these :
# ANT_PATH_MATCHER is added to avoid NULL error in SwaggerConfig
spring.mvc.pathmatch.matching-strategy = ANT_PATH_MATCHER
server.port=8081
# Spring Config Server URL of Config Server Microservice :
spring.config.import=configserver:http://localhost:8888
# Environment configuration which you want to load :
spring.profiles.active=dev
In spring-boot-client's jenkins build job, this is what I have :
Now, theoretically, I believe that deploying 1 config-server and 1 client-app in the same linux machine should be possible. I just don't know how to properly configure it in Jenkins.
I have this spring cloud config client in pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>3.1.3</version>
</dependency>
I have a copy of the spring-config-server app and spring-boot-client app in my local machine. I just start/run both and it works.
I am a beginner in Jenkins and I do everything in UI. This is just a build task with scp and ssh commands executed in shell to deploy.
I'd appreciate any help or comment.
Thank you.

Cannot override properties in Hazelcast.yaml for Spring Boot Application

I have Spring Boot application with Hazelcast (use 4.2 and also try to use 4.0.3 of hazelcast-all dependency). Hazelcast is configured for embedded topology. I use TCP-IP network join way. Properties for Hazelcast are set using file Hazelcast.yaml and Spring Boot property: spring.hazelcast.config (Spring by default use this name for Hazelcast config, it is redundant).
In property member-list I indicate IP addresses of two machines in one subnet (e.g. 192.0.0.1 and 192.0.0.2).
I build application in Docker using image based on Alpine on OpenJdk. Image includes start java -jar command as ENTRYPOINT.
PROBLEM PREMISE:
I run two docker containers on two machines described earlier. I forward only port 5701 (using -p) on both containers. And containers don't see each other. Spring Boot logs show that the container network is being used.
PS:
All work if run docker with --net host.
Also all work if I package Spring Boot application with property public-address in Hazelcast.yaml for two containers - once package with value 192.0.0.1, the other with value 192.0.0.2. Spring Boot Hazelcast instances see each other using network of machine (192.0.0.1 and 192.0.0.2).
PROBLEM:
I try to override property public-address in Hazelcast.yaml using:
docker run -e HZ_NETWORK_PUBLICADDRESS=192.0.0.1
export HZ_NETWORK_PUBLICADDRESS=192.0.0.1 && docker run
JAVA_OPTS="-Dhz.network.public-address=192.0.0.1"
JAVA_OPTS="-Dhazelcast.local.publicAddress=192.0.0.1"
JAVA_OPTS="-Dhazelcast.config=/mnt/overrided_hazelcast.yaml"
ENV HZ_NETWORK_PUBLICADDRESS=192.0.0.1 - in Dockerfile
ENTRYPOINT java -jar -Dhz.network.public-address=192.0.0.1 my-app.jar
Nothing works. Does anyone know why it is not possible to override property public-address in the Hazelcast.yaml at startup?
Or maybe anyone knows how I can run two Spring Boot applications with embedded Hazelcast in separate Docker containers on separate machines.
The way you set up Hazelcast public address is correct, at least starting from Hazelcast 4.1 where the Config Override feature was added.
To check the working version, you can have a look at Hazelcast Guide: Embedded Hazelcast on Kubernetes. Instead of Hazelcast Kubernetes configuration, you can use TCP-IP. The following Hazelcast configuration worked for me (my host IP is 172.22.41.210).
hazelcast:
cluster-name: hazelcast-cluster
network:
join:
tcp-ip:
enabled: true
member-list:
- 172.22.41.210:5701
- 172.22.41.210:5702
Then, building and starting two applications should form a cluster.
$ mvn package && docker build -t hazelcast-embedded .
$ docker run --rm -e HZ_NETWORK_PUBLICADDRESS=172.22.41.210 -p 5701:5701 hazelcast-embedded
$ docker run --rm -e HZ_NETWORK_PUBLICADDRESS=172.22.41.210:5702 -p 5702:5701 hazelcast-embedded
You should see that the cluster was formed in the application logs.
Members {size:2, ver:2} [
Member [172.22.41.210]:5701 - 21af9e1a-7e98-4305-905c-451ee23486c3 this
Member [172.22.41.210]:5702 - 0507d970-1f31-4df3-9ea5-8c3981eb7c98
]

Spring boot running as container issues

I am running a spring boot with REST API inside a docker container. Everything seems to work fine when i run from eclipse or as jar. But when i dockerize it and run i am facing below issues
First
Not able to access REST Endpoint within container.
http://localhost:9000/ --> works But
http://localhost:9000/api/v1/test --> it does not identify.
However i can run it from swagger.
Second issue org.postgresql.util.PSQLException: ERROR: permission denied for schema < schema_name >
However i have given all permissions for the schema like
GRANT ALL ON SCHEMA < schemaname> TO < username>;
GRANT USAGE ON SCHEMA < schemaname> TO < username>;
These issues are only when i try to run from a container.
Commands use for docker
docker run -p 9000:9000 < image name >
Am using spring boot 2.1.9
Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD run-app.sh run-app.sh
RUN chmod +x run-app.sh
EXPOSE 9000
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} dummy.jar
ENTRYPOINT ./run-app.sh
run-app.sh
java $JAVA_OPTS -jar /dummy.jar
My postgresql Db is running in aws.
My spring boot is able to start, but only while my API is querying i am facing the exception
Can you share dockerfile content if possible, would like to see what commands you have given with endpoints. and for postgresql which you are using, is it embeded in docker with spring boot app or another server?
I do already setup spring boot with nginx and postgresql dockerized but in different servers/containers which working pretty smooth on production.
For first issue I will need more details.
For second issue, the problem is two containers are not on the same network and hence service container can't communicate with psql container. You can actually create a docker-compose.yml file to run those on same network. Or create a network and join the containers on that network.

Connection refused: accessing a spring boot application running in docker container

I have my spring boot application and mysql database running in separate docker containers. I am able to access server database from my host.
My application.properties for Spring boot application looks like below:
spring.datasource.url=jdbc:mysql://benefitsmysql:3308/benefitsmysql
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
# ====================================================================================
# = SSL Configuration
# ====================================================================================
#security.basic.enabled=false
server.port=8443
server.ssl.key-store=keystore.jks
server.ssl.key-store-password=*******
server.ssl.keyStoreType=jks
server.ssl.keyAlias=tomcatselfsigned
I am building a docker container image by using maven plugin for docker. My Dockerfile looks like below:
FROM java:8
VOLUME /tmp
ADD Benefits.jar Benefits.jar
EXPOSE 8443
RUN bash -c 'touch /Benefits.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/Benefits.jar"]
I am starting docker container for spring boot application like below:
docker run -p 8443:8443 --name benefits --link benefitsmysql:mysql -d c794a4d0c634
and if I do docker ps -a, I get following output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8070c575b6dd c794a4d0c634 "java -Djava.secur..." 2 minutes ago Up 2 minutes 0.0.0.0:8443->8443/tcp benefits
aa417df08b94 mysql:5.6 "docker-entrypoint..." 2 days ago Up 2 days 0.0.0.0:3308->3306/tcp benefitsmysql
f55a2a7ac487 hello-world "/hello" 2 days ago Exited (0) 2 days ago gifted_lalande
Now when I access my spring boot application running inside docker container from my windows machine like https://192.168.99.103:8443/home, I get connection refused error ERR_CONNECTION_REFUSED.
What am I missing in this configuration?
yogsma
I read your blog, and apply your solve, but docker-machine ip didn't solve my problem.
Then I realize docker containers can't communicate with 127.0.0.1 and I use their container ip
docker inspect <container_id>
then find IpAddress.
This ip address is solves my problem.I dont need to use docker-machine ip

Can't connect Java program to MySQL using Docker

I'm learning docker and trying to put my Java web application using Tomcat to container. I followed some basic tutorial but i found no solution to work properly to me. If i run my database and java containers i get the error:
SEVERE: Unable to create initial connections of pool.
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:981)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:339)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2253)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2286)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2085)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:795)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)
MySQL Dockerfile
FROM mysql:latest
ENV MYSQL_DATABASE=db_name #name of db that is required by Java program
Run by:
docker run --name db_name -e MYSQL_ROOT_PASSWORD=root -d db_name
Java Dockerfile
FROM tomcat:7.0.70-jre8
ADD deploy /usr/local/tomcat/webapps #extracted .war
ADD jdbc /usr/local/tomcat/lib #MySQL jdbc drivers
ADD context /usr/local/tomcat/conf #context.xml
Run by:
docker run --name app_name --link db_name:db_name -p 8080:8080 -d app_name
Whole configuration was running properly when i was running it locally in Eclipse.
Because you do not provide the full stack tace, which would show what connection string tomcat is using, I have to guess that you do not provide the proper connection string to your tomcat conainer. You have to supply an connectionstring like:
jdbc:mysql://database_container_name:3306/database_name
into your tomcat config.
BTW:
You should rearrange you lines in the Tomcat Dockerfile to
FROM tomcat:7.0.70-jre8
ADD jdbc /usr/local/tomcat/lib #MySQL jdbc drivers
ADD context /usr/local/tomcat/conf #context.xml
ADD deploy /usr/local/tomcat/webapps #extracted .war
Because docker can cache build layers. With the old Order your war is the first layer of the image and changes every time you make a change to your application causing the folliwing layers to be rebuild every time, even if they did not change. The new order uses the docker chache better. With this order the never changing MySQL driver is always cached and the config also does not alter as fast as the war.
In this example the effect may be minimal, but if you build bigger images with more layers and lengthy build steps (like apt-get install smth) the chache can significantly speed up your build.

Categories