How to connect to MySQL container on Docker using Spring Boot project - java

I am trying to run a Spring Boot application where db has to be connected to a MySQL container on Docker. I used following code and commands.
Application properties:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://mysqldb:3306/practice
spring.datasource.username=root
spring.datasource.password=CVnit1234!
spring.jpa.show-sql=true
spring.sql.init.platform=mysql
spring.sql.init.mode=always
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
Commands used for creating container & running it on Docker:
Pulling mysql image from Docker Hub:
docker pull mysql
Creating a container:
docker run --name mysqldb --network spring-net -p 3307:3306 -e MYSQL_ROOT_PASSWORD=password MYSQL_DATABASE=practice -d mysql:latest
After this command, a container is created and even it is up and working fine. I was able to login to sql bash and execute some queries.
I tried with multiple jdbc urls:
jdbc:mysql://mysqldb:3306/practice
jdbc:mysql://mysqldb:3307/practice
jdbc:mysql://mysqldb/practice
jdbc:mysql://host.docker.internal:3306/practice
jdbc:mysql://host.docker.internal:3307/practice
None of this worked, but I was able to connect to localhost:3306 and localhost:3307.
Below is my spring boot code. When I am trying to connect through the Spring Boot application, I was getting the following error.
com.mysql.cj.jdbc.exceptions.CommunicationsException:Communication link failure
The problem over here is when I am trying to connect to localhost the application is up and working, but when trying to connect to mysql container, I was not able to connect.

Check your network to ensure that the application network is connected to the MySQL network

Related

Java application is not connecting with Postgres Database

I recently setup a java application in my spring-boot. I'm getting this error when i run it:
org.postgresql.util.PSQLException: The connection attempt failed.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:315)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:51)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:225)
at org.postgresql.Driver.makeConnection(Driver.java:465)
at org.postgresql.Driver.connect(Driver.java:264) ........
Caused by: java.net.UnknownHostException: postgres ........
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-02-03 17:24:15 - Application run failed
My application-dev.properties file in src/main/resources/ has this code:
spring.datasource.url=jdbc:postgresql://localhost:5432/sofra_hybrid_7?useUnicode=yes&characterEncoding=UTF-8
spring.datasource.username=postgres
spring.datasource.password=admin
I have made the database too as well in the postgres server with username "postgres" and pass "admin:
lalarukh=# CREATE DATABASE sofra_hybrid_7;
CREATE DATABASE
lalarukh=# grant all privileges on database sofra_hybrid_7 to postgres ;
GRANT
I have even also used the jdbc postgres jar file inside the application to make the connection but all in vain.
Seeking Help!
I can't run my java application as postgres can't make connection with my app in spring boot.
I also faced the same issue and after a lot of working I finally resolved it this way:
As you're receiving unknown host means that your application can't detect your this file: application-dev.properties
You shall make this application.yml inside your project (yourprojectdirectory/application.yml) and this will automatically detects the DB information and all.
As you're using postgres as DB so, add this code inside this file:
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql:db_name
username: your-postgres-username
password: your-postgres-password
Run this command for application running: mvn spring-boot:run -Dspring-boot.run.profiles

Cannot connect to Wildfly in Dockerfile

I'm creating a custom Dockerfile with extensions for official keycloak docker image. I want to change web-context and add some custom providers.
Here's my Dockerfile:
FROM jboss/keycloak:7.0.0
COPY startup-config.cli /opt/jboss/tools/cli/startup-config.cli
RUN /opt/jboss/keycloak/bin/jboss-cli.sh --connect --controller=localhost:9990 --file="/opt/jboss/tools/cli/startup-config.cli"
ENV KEYCLOAK_USER=admin
ENV KEYCLOAK_PASSWORD=admin
and startup-config.cli file:
/subsystem=keycloak-server/:write-attribute(name=web-context,value="keycloak/auth")
/subsystem=keycloak-server/:add(name=providers,value="module:module:x.y.z.some-custom-provider")
Bu unfortunately I receive such error:
The controller is not available at localhost:9990: java.net.ConnectException: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: WFLYPRT0053: Could not connect to remote+http://localhost:9990. The connection failed: Connection refused
The command '/bin/sh -c /opt/jboss/keycloak/bin/jboss-cli.sh --connect --controller=localhost:9990 --file="/opt/jboss/tools/cli/startup-config.cli"' returned a non-zero code: 1
Is it a matter of invalid localhost? How should I refer to the management API?
Edit: I also tried with ENTRYPOINT instead of RUN, but the same error occurred during container initialization.
You are trying to have Wildfly load your custom config file at build-time here. The trouble is, that the Wildfly server is not running while the Dockerfile is building.
Wildfly actually already has you covered regarding automatically loading custom config, there is built in support for what you want to do. You simply need to put your config file in a "magic location" inside the image.
You need to drop your config file here:
/opt/jboss/startup-scripts/
So that your Dockerfile looks like this:
FROM jboss/keycloak:7.0.0
COPY startup-config.cli /opt/jboss/startup-scripts/startup-config.cli
ENV KEYCLOAK_USER=admin
ENV KEYCLOAK_PASSWORD=admin
Excerpt from the keycloak documentation:
Adding custom script using Dockerfile
A custom script can be added by
creating your own Dockerfile:
FROM keycloak
COPY custom-scripts/ /opt/jboss/startup-scripts/
Now you can simply start the image, and the built features in keycloak (Wildfly feature really) will go look for a config in that spedific directory, and then attempt to load it up.
Edit from comment with final solution:
While the original answer solved the issue with being able to pass configuration to the server at all, an issue remained with the content of the script. The following error was received when starting the container:
=========================================================================
Executing cli script: /opt/jboss/startup-scripts/startup-config.cli
No connection to the controller.
=========================================================================
The issue turned out to be in the startup-config.cli script, where the jboss command embed-server was missing, needed to initiate a connection to the jboss instance. Also missing was the closing stop-embedded-server command. More about configuring jboss in this manner in the docs here: CHAPTER 8. EMBEDDING A SERVER FOR OFFLINE CONFIGURATION
The final script:
embed-server --std-out=echo
/subsystem=keycloak-server/theme=defaults/:write-attribute(name=cacheThemes,value=false)
/subsystem=keycloak-server/theme=defaults/:write-attribute(name=cacheTemplates,value=false)
stop-embedded-server
WildFly management interfaces are not available when building the Docker image. Your only option is to start the CLI in embedded mode as discussed here Running CLI commands in WildFly Dockerfile.
A more advanced approach consists in using the S2I installation scripts to trigger CLI commands.

spring boot Eureka microservice discovery and registration fails in docker

I created a eureka server microservice and a normal microservice , usually when I run both the service separately using STS tool service discovery and registration works fine , but whenever i tried to launch in docker that time registration fails.
Code is below -
Eureka Server
application.properties
spring.application.name=eureka-service
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=eureka-service
eureka.instance.prefer-ip-address=true
eureka.server.wait-time-in-ms-when-sync-empty=0
Dockerfile
FROM openjdk:8
ADD target/SpringEureka-1.0.jar SpringEureka-1.0.jar
EXPOSE 8761
ENTRYPOINT ["java","-jar","SpringEureka-1.0.jar"]
Normal Microservice
application.properties
server.port: 8010
spring.application.name=eureka-client
eureka.client.register-with-eureka=true
eureka.client.fetch-registry= true
eureka.client.service-url.default-zone=http://localhost:8761/eureka/
eureka.client.proxy-host=localhost
eureka.instance.prefer-ip-address=true
Dockerfile
FROM openjdk:8
ADD target/HystrixTest-1.0.jar HystrixTest-1.0.jar
EXPOSE 8010
ENTRYPOINT ["java","-jar","HystrixTest-1.0.jar"]
Are you link the HystrixTest container to Eureka Server container?
You can get more detail in here: https://docs.docker.com/network/links/
The better question if you post docker-compose file or your cmd when starting the container.
I think everything that you did is all right you just need to enable the ports using the
docker run -P 8761:8761 <your_docker_image> command.
And change also the configuration from eureka.instance.hostname=eureka-service to eureka.instance.hostname=localhost

Connecting an Oracle DB Container and a Java application Container (Docker)

I am now working on a docker project with two docker containers - one for the oracle db and the other with a java application.
The container for oracle db is working ok. I used the already built image for oracle and created my tablespaces and users in it.
Commands I used to pull and use the oracle db container is as given below:
docker pull wnameless/oracle-xe-11g
docker run -d -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g
Now I have my own Java application that interacts with the oracle db and I run it using the command given below:
docker run -it --name mypgm myrepo/oracletesting
It runs an interactive java program that asks for the Oracle DB details and allows users to interact with the DB.
However I could not figure out how I have to specify details such as
Driver Name, Connection URL, Username, and Password
The values I gave are as given below:
Driver Name: oracle.jdbc.OracleDriver
Connection URL:jdbc:oracle:thin:#localhost:1521:orcl11g
Username: imtheuser
Password: **********
I dont know whats going wrong where but its not working.
I tried giving different inputs for Connection URL after inspecting the docker container ip address as well:
Connection URL: jdbc:oracle:thin:#172.17.0.2:1521:orcl11g
Am I giving the Connection URL and/or the port number correct? Can someone help me out to correctly connect these two containers and to get the project moving?
Thanks for your kind help..
You have to link the containers.
The oracle container should have a name.
try the following:
docker network create my-network # Create a network for containers
docker run -d -p 49160:22 -p 49161:1521 --network my-network --name oracle-db -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g
docker run -it --network my-network --name mypgm myrepo/oracletesting
Use as connection url to following string jdbc:oracle:thin:#oracle-db:1521:orcl11g
You can use a domain name in oracle connection string: oracle.dbhost.com, and use a --addhost oracle.dbhost.com:[ip address] when running your app in docker, or configure a dns to resolve the domain name.

Docker: Linking Spring Boot container with Mongo DB container

How can I link my Spring Boot application container with MongoDB container?
Spring Boot app is using MongoDBRespository which by default connects to localhost:27017.
You should use container linking. From the docs:
When you set up a link, you create a conduit between a source container and a recipient container. The recipient can then access select data about the source
When two containers are linked, Docker will set some environment variables in the target container to enable programmatic discovery of information related to the source container.
Basically what this means is the following
your MongoDB-container should expose some ports (either via the EXPOSE entry in the Dockerfile or via the -p option to docker run).
your Spring Boot-container should be started with the --link option that points to the MongoDB-container.
The MongoDBRepository should be configured to use the address that is provided in the environment variables by the linking.
Check out this article on how to link containers for more info.
#Himanshu Yadav , you can try this resource. it did solve my problem. :-) It has got a full tutorial in that regard
https://www.jiwhiz.com/blogs/Spring_Boot_Docker_MySQL_Demo
Quote
docker run -p 8080:8080 --name demo-app --link demo-mysql:mysql -d jiwhiz/spring-boot-docker-mysql
I wonder if you got this to work by linking containers, it didn't work for me, tried using a linked container alias as a dbhost name in my Springboot app. I did not try it as MongoClientURI though.
I did opt a work around, with mongodb containers and spring apps containers, I had to set up mongo containers host and port to spring app containers while creating the apps containers as Containers ENV variables , as shown below
Mongo container
docker run -d -p 27027:27017 -p 28027:28017 --name mongodb --volumes-from dbdata iamiddy/mongodb
SpringBoot Apps containers
docker run -d -p 8000:8080 --name AppDockerContainer
-e db.host.name=EC2-HOSTING-MONGO-CONTAINER
-e db.host.port=DB-HOST-PORT AppDockerImage
application.properties
db.host.port=27017
db.host.name=localhost
MongoConfig
public class MongoRepositoryConfig extends AbstractMongoConfiguration {
#Value("${db.host.port}")
private int port;
#Value("${db.host.name}")
private String host;
#Value("${db.name}")
private String dbname;
#Override
public Mongo mongo() throws Exception {
ServerAddress serverAdress = new ServerAddress(host,port);
Mongo mongo = new MongoClient(serverAdress);
mongo.setWriteConcern(WriteConcern.ACKNOWLEDGED);
return mongo;
}
public #Bean MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), getDatabaseName());
}
#Override
protected String getDatabaseName() {
return dbname;
}
}
As docker links are now deprecated, one can use user defined networks to achieve communication between containers.
Referring to Docker Networking, docker has 3 different types of networks - Bridge, Host, Network. Using docker network ls you can list all networks currently defined. By default docker comes with 1 for each type pre-configured.
While running your container, one can specify(--network=abcd) network the process will join - by default its the docker0 of type bridge.
Now, for the problem statement in the question here, the simplest approach is to use --network=host while launching mongo & spring-boot-app container.
docker run -d -P --name=my-mongo --network=host mongo:latest
Then in your Spring boot app, you will have something like this:-
spring:
application:
name: my-app
data:
mongodb:
database: app
host: 192.168.99.100 // your machine private ip.
port: 27017
Run you spring boot app from image using :-
docker run -d -P --name=my-boot-app --network=host my-app-image
You can then use/reach mongo & app instances as if they were run without docker.
(While using docker-toolbox on Windows, you are actually running docker inside a VM that has different IP - I found it to be 192.168.99.100 . So remember to use this ip instead of your local ip)

Categories

Resources