Hello guys !
It's my first so I will try to make the best that I can.
I want to create an app which is running with Springboot framework and I would like to connect it to a docker container which embeds MySQL (but the spring boot app is not running on docker)
So I have followed this post
I have made my docker-compose:
db:
image: mysql
ports:
- '3306:3306'
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=users
volumes:
- ../data:/var/lib/mysql
and I run it with this command :
docker-compose run --service-ports db
All is fine, so now I change my application.properties on spring boot :
## Server Properties
server.port= 5000
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url= jdbc:mysql://127.0.0.1:3306/users?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username= root
spring.datasource.password= secret
## Hibernate Properties
#The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto = update
## Hibernate Logging
logging.level.org.hibernate.SQL= DEBUG
## Jackson Properties
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS= false
spring.jackson.time-zone= UTC
But When I run my app, I have this error :( :
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
I'm on MacOS...
I tried to follow callicoder's course ...
https://www.callicoder.com/spring-boot-spring-security-jwt-mysql-react-app-part-1/
Thanks for your help :)
The problem is that the db container is not running on localhost but rather inside a mini Linux VM since you are on a MAC.
Thus to connect to the database you need to use the IP address of the machine where the container is running. To do that run the command docker-machine ip default. This will return the IP address which you would use in the connection url rather than localhost:
spring.datasource.url= jdbc:mysql://<docker-machine-ip>:3306/users?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
Related
I have created a docker-compose.yml to run a postgresql database . While the image is pulled and can run succesfully I am unable to connect to my database through a spring boot project I have . When I try to run my spring boot project after succesfully running my postgresql container with docker-compose up I get the error org.postgresql.util.PSQLException: The connection attempt failed. and a huge text of error logs underneath where I spotted the cause.
Caused by: java.net.UnknownHostException: postgresqldb
which is the name of my db image .
My docker-compose.yml at the root of my spring project
version: '3.1'
services:
postgresqldb:
image: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=booksdb
My application.properties in my spring boot project .
server.port=8081
server.servlet.context-path=/rest
#Postgres
spring.datasource.url=jdbc:postgresql://postgresqldb:5432/booksdb
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create
#JWT
jwt.secret-key=someKey
I would appreciate your help .
Maybe you should add a hostname to the container:
version: '3.1'
services:
postgresqldb:
image: postgres
hostname: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_PASSWORD=postgres
- POSTGRES_USER=postgres
- POSTGRES_DB=booksdb
docker uses its own network and resolves hostname internally. You should assign a hostname to the running container that may be found for the rest of the containers.
I'm attempting to run a Spring Boot app that connects a Postgres DB using:
docker-compose.yml (for Postgres) :
version: '3'
services:
postgres-db:
container_name: postgres-db
image: postgres:latest
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_password
POSTGRES_DB: shorten-db
To run the Postgres DB:
docker-compose up
.Dockerfile (for the Spring Boot app) :
FROM openjdk:12-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
In order to run the Spring app using Docker I use:
mvn package
docker build -t url-shorten/url-shorten-docker .
docker run -p 8080:8080 url-shorten/url-shorten-docker
But I receive the error when starting when running above docker command:
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
In Spring application.properties I connect to the DB using:
spring.datasource.url=jdbc:postgresql://localhost:5432/shorten-db
I think this error is due to the Spring Boot app is running in a different container to DB so it cannot find the DB on localhost. Is there an idiomatic way of connecting the Spring Book docker container to the DB container. Or do I have do access the IP address of my machine and use this address to connect to the Postgres DB running on Docker?
Yes, you can't use localhost in this situation
spring.datasource.url=jdbc:postgresql://postgres-db:5432/shorten-db
In Spring application.properties, try to change DB config to:
spring.datasource.url=jdbc:postgresql://postgres-db:5432/shorten-db
In container networks, You need to use the container name as a host.
You can add both DB and app containers to one Docker network and change PostgreSQL host in datasource URL to postgres-db. Then Spring app will work with your DB.
My Application Properties
spring.profiles.include=docker
spring.datasource.url=jdbc:mysql://dbwebrestful:3306/webrestful
spring.datasource.username=root
spring.datasource.password=webrestful
and my docker-compose.yml
on this link
but still error like this
what should I do to fix this issue ?
If your docekr and mysql are on same instance then try this
spring.datasource.url=jdbc:mysql://host.docker.internal:3306/yourdbname
So i have production server that i want to connect to with Mysql Workbench.
When i start application all runs fine, so i conenct to it via IP of the server and credentials.
My docker-compose looks like this :
...
workaround-mysql:
container_name: workaround-mysql
image: mysql
environment:
MYSQL_DATABASE: workaround
MYSQL_USER: someuser
MYSQL_PASSWORD: somepass
MYSQL_ROOT_PASSWORD: somepassss
MYSQL_ROOT_HOST: %
ports:
- "3308:3306"
restart: always
....
So on my prod machine i run spring application, mysql, nginx.
When i try to connect via workbench this is the error i get :
Error 10061.
I dont understand what im doing wrong. I had no trouble when i was doing local testing. Workbench worked fine.
Is there some additional settings i have to do ? And can i do these required settings via docker-compose?
On my firewall, i have set accept connection to mysql port:
Oh and the additional note : I get that error right when i press connect on workbench, I dont even have prompt to enter password.
And docker compose up output for mysql part :
Maybe it is just a typo, but you put 3308 as a port in your docker-compose file. So either fix that to 3306 or use 3308 when connecting.
MacOS + Docker (Version 17.12.0-ce-mac49 (21995)) here. I am trying to Dockerize an existing Spring Boot app. Here's my Dockerfile:
FROM openjdk:8
RUN mkdir /opt/myapp
ADD build/libs/myapp.jar /opt/myapp
ADD application.yml /opt/myapp
ADD logback.groovy /opt/myapp
WORKDIR /opt/myapp
EXPOSE 9200
ENTRYPOINT ["java", "-Dspring.config=.", "-jar", "myapp.jar"]
Here's my Spring Boot application.yml config file. As you can see it expects Docker to inject environment variables from an env file:
logging:
config: 'logback.groovy'
server:
port: 9200
error:
whitelabel:
enabled: true
spring:
cache:
type: none
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://${DB_HOST}:3306/myapp_db?useSSL=false&nullNamePatternMatchesAll=true
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
testWhileIdle: true
validationQuery: SELECT 1
jpa:
show-sql: false
hibernate:
ddl-auto: none
naming:
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
properties:
hibernate.dialect: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.cache.use_second_level_cache: false
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: false
hibernate.hbm2ddl.auto: validate
myapp:
detailsMode: ${DETAILS_MODE}
tokenExpiryDays:
alert: 5
jwtInfo:
secret: ${JWT_SECRET}
expiry: ${JWT_EXPIRY}
topics:
adminAlerts: admin-alerts
Here's my myapp-local.env file:
DB_HOST=localhost
DB_USERNAME=root
DB_PASSWORD=
DETAILS_MODE=Terse
JWT_SECRET=12345==
JWT_EXPIRY=86400000
It's worth noting that above in the env file, I have tried localhost, 127.0.0.1 and 172.17.0.1 and all of them produce identical errors below.
Then I build the container:
docker build -t myapp .
Success! Then I run the container:
docker run -it -p 9200:9200 --net="host" --env-file myapp-local.env --name myapp myapp
...and I watch as the container quickly dies with MySQL connection-related exceptions (can't connect to the MySQL machine running locally). I can confirm that the Spring Boot app has no problem connecting to MySQL when it runs as an executable ("fat") jar outside of Docker, and I can confirm that the local MySQL instance is up and running and is perfectly healthy.
Unable to connect to database. }com.mysql.cj.jdbc.exceptions.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 com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:590)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:57)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:1606)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:633)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:347)
When I turn TRACE-level logging on, I see it is trying to connect to:
url=jdbc:mysql://localhost:3306/myapp?useSSL=false&nullNamePatternMatchesAll=true
So it does look like Docker is properly injecting the env file's vars into the Spring YAML-based config. So this doesn't feel like a config issue, moreover an isse with the container speaking to the MySQL port running on the Docker host.
Can anybody see where I'm going awry?
Accessing the host machine from within a container is not recommended. Usually it can be solved by wrapping service you need into a container and accessing it via container name.
There is no solution, there are only workarounds, you can use one of them:
On Mac you can access the host services using docker.for.mac.host.internal DNS name.
You need to set environment variable like this:
DB_HOST=docker.for.mac.host.internal
And refer to the DB_HOST from your connection string.
For more details see the documentation:
From 17.12 onwards our recommendation is to connect to the special
Mac-only DNS name docker.for.mac.host.internal, which resolves to the
internal IP address used by the host.
Note: Having --net="host" doesn't let you reach the host machine via localhost. localhost always points to local machine, but in case if it is invoked from within a container it points to the container itself.
So basically Docker app is not in the same network as the host you're running it from and that's why you can't access MySQL by pointing to localhost (because this is another network from Docker's point of view).
What you could try is to run docker with --net="host" option and then it will share the network with its host.
You can find better explanation on this issue in this topic From inside of a Docker container, how do I connect to the localhost of the machine?