Spring boot JDBC can't connect to mysql in docker container - mysql

I'm trying to run a spring boot app (as a simple REST api) and mysql server in two separate docker containers. But, I can't get the jdbc connection in the spring app to connect to mysql. They are both working independently and the implementation works when I run spring boot and mysql locally.
docker-compose.yml
version: '3'
services:
database:
image: mysql:latest
container_name: mysqldb
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_ROOT_PASSWORD=password
expose:
- 3306
ports:
- 3306:3306
networks:
- backend
volumes:
- "dbdata:/var/lib/mysql"
web:
container_name: springboot
build: .
depends_on:
- database
expose:
- 8080
ports:
- 8080:8080
networks:
- backend
networks:
backend:
volumes:
dbdata:
In the spring boot app:
val dataSource = DriverManagerDataSource()
dataSource.setDriverClassName("com.mysql.jdbc.Driver")
dataSource.setUrl("jdbc:mysql://mysqldb:3306/$dbName?characterEncoding=latin1")
dataSource.username = "dev"
dataSource.password = "password"
val jdbcTemplate = JdbcTemplate(dataSource)
Error returned from spring boot:
{
"status": 500,
"error": "Internal Server Error",
"message": "Failed to obtain JDBC Connection; nested exception is com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure\n\nThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server."
}
I AM able to connect to the mysql container from the spring boot container via the mysql cli. So, it appears the springboot container is able to resolve "mysqldb."
This seems like it should be pretty simple. I'm not sure where the error lies but I would guess it has something to do with spring boots inner workings that I am unfamiliar with.

change this dataSource.setUrl("jdbc:mysql://mysqldb:3306/$dbName") , to:
dataSource.setUrl("jdbc:mysql://database:3306/$dbName")
your service name in compose is database, so you need to use it

Related

springboot docker cannot connect to mysql when using docker-compose [duplicate]

I have a Java Spring Boot app which works with a Postgres database. I want to use Docker for both of them. I initially put just the Postgres in Docker, and I had a docker-compose.yml file defined like this:
version: '2'
services:
db:
container_name: sample_db
image: postgres:9.5
volumes:
- sample_db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=sample
- POSTGRES_USER=sample
- POSTGRES_DB=sample
- PGDATA=/var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
sample_db: {}
Then, when I issued the commands sudo dockerd and sudo docker-compose -f docker-compose.yml up, it was starting the database. I could connect using pgAdmin for example, by using localhost as server and port 5432. Then, in my Spring Boot app, inside the application.properties file I defined the following properties.
spring.datasource.url=jdbc:postgresql://localhost:5432/sample
spring.datasource.username=sample
spring.datasource.password=sample
spring.jpa.generate-ddl=true
At this point I could run my Spring Boot app locally through Spring Suite, and it all was working fine. Then, I wanted to also add my Spring Boot app as Docker image. I first of all created a Dockerfile in my project directory, which looks like this:
FROM java:8
EXPOSE 8080
ADD /target/manager.jar manager.jar
ENTRYPOINT ["java","-jar","manager.jar"]
Then, I entered to the directory of the project issued mvn clean followed by mvn install. Next, issued docker build -f Dockerfile -t manager . followed by docker tag 9c6b1e3f1d5e myuser/manager:latest (the id is correct). Finally, I edited my existing docker-compose.yml file to look like this:
version: '2'
services:
web:
image: myuser/manager:latest
ports:
- 8080:8080
depends_on:
- db
db:
container_name: sample_db
image: postgres:9.5
volumes:
- sample_db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=sample
- POSTGRES_USER=sample
- POSTGRES_DB=sample
- PGDATA=/var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
sample_db: {}
But, now if I issue sudo docker-compose -f docker-compose.yml up command, the database again starts correctly, but I get errors and exit code 1 for the web app part. The problem is the connection string. I believe I have to change it to something else, but I don't know what it should be. I get the following error messages:
web_1 | 2017-06-27 22:11:54.418 ERROR 1 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
web_1 |
web_1 | 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
Any ideas?
Each container has its own network interface with its own localhost. So change how Java points to Postgres:
spring.datasource.url=jdbc:postgresql://localhost:5432/sample
To:
spring.datasource.url=jdbc:postgresql://db:5432/sample
db will resolve to the proper Postgres IP.
Bonus. With docker-compose you don't need to build your image by hand. So change:
web:
image: myuser/manager:latest
To:
web:
build: .
I had the same problem and I lost some time to understand and solve this problem:
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.
I show all the properties so that everyone understands.
application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
spring.jpa.hibernate.ddl-auto=update
docker-compose.yml:
version: "3"
services:
springapp:
build: .
container_name: springapp
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/testdb
ports:
- 8000:8080
restart: always
depends_on:
- db
db:
image: postgres
container_name: db
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=testdb
- PGDATA=/var/lib/postgresql/data/pgdata
ports:
- 5000:5432
volumes:
- pgdata:/var/lib/postgresql/data
restart: always
volumes:
pgdata:
For start spring application with local database we use url localhost.
For connect to container with database we need change 'localhost' on your database service, in my case 'localhost' to 'db'.
Solution: add SPRING_DATASOURCE_URL environment in docker-compose.yml wich rewrite spring.datasource.url value for connect:
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/testdb
I hope this helps someone save his time.
You can use this.
version: "2"
services:
sample_db-postgresql:
image: postgres:9.5
ports:
- 5432:5432
environment:
- POSTGRES_PASSWORD=sample
- POSTGRES_USER=sample
- POSTGRES_DB=sample
volumes:
- sample_db:/var/lib/postgresql/data
volumes:
sample_db:
You can use ENV variable to change the db address in your docker-compose.
Dockerfile:
FROM java:8
EXPOSE 8080
ENV POSTGRES localhost
ADD /target/manager.jar manager.jar
ENTRYPOINT exec java $JAVA_OPTS -jar manager.jar --spring.datasource.url=jdbc:postgresql://$POSTGRES:5432/sample
docker-compose:
`
container_name: springapp
environment:
- POSTGRES=db`

Spring boot + MySQL. Docker

I`m create simple app on spring boot + MySQL. On local pc it works correctly, but when i package it in docker, i catch some errors: container with DB works well, i can connect to it via workbanch, the container with the application crashes on startup with an error:
"java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
...
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: 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.
...
Caused by: java.net.ConnectException: Connection refused
..."
My Dockerfile:
FROM openjdk:17-alpine
ADD /target/tests-0.0.1-SNAPSHOT.jar backend.jar
ENTRYPOINT ["java", "-jar", "backend.jar"]
My docker-compose.yml:
version: '3'
services:
personsdb:
image: 'mysql:8.0.31'
container_name: 'persons-db'
environment:
- 'MYSQL_ROOT_PASSWORD=Qwer'
- 'MYSQL_DATABASE=persons'
- 'MYSQL_USER=mysql'
- 'MYSQL_PASSWORD=Qwer'
ports:
- '3305:3306'
app:
container_name: 'persons-app'
ports:
- 8088:8080
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://personsdb:3305/persons?autoReconnect=true&useSSL=false
depends_on:
- 'personsdb'
build: ./
My application.properties:
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://personsdb:3305/persons
spring.datasource.username=root
spring.datasource.password=Qwer
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
I tried to
run: docker-compose down --rmi all
rename service
upgrade MySQL Connector
add more dependences to pom.xml
...
It seems you have to create a bridge to let them communicate.
Please check the link below
https://www.tutorialworks.com/container-networking/
when they are in the same host, below configuration also worked for me.
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://host.docker.internal:5432/DB-NAME

Error when accessing from one dotnet core docker container to a mysql docker container

I tried to build an application consisting on DotNet Core and a MySQL docker containers using docker-compose.
I used Entity Framework and I succeeded making the connection and updating database via command with this connection string:
"server=127.0.0.1;database=hellofreshgo;user=root;password=hellofreshgo;Port=3306"
But when I dockerize or containerize my netcore app and try to retrive data and connect with my mysql container with this connection string and the the following docker-compose file:
"server=mysql;database=hellofreshgo;user=root;password=hellofreshgo;Port=3306"
version: '3.4'
services:
hfgo.backendtest.api:
image: ${DOCKER_REGISTRY-}hfgobackendtestapi
build:
context: .
dockerfile: src/Presentations/HFGO.BackendTest.API/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:8080;http://+:80
volumes:
- ./:/server/http
links:
- mysql
ports:
- "8080:8080"
depends_on:
- mysql
volumes:
- ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
- ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
mysql:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
ports:
- "3306:3306"
environment:
LC_ALL: C.UTF-8
MYSQL_ROOT_PASSWORD: hellofreshgo
MYSQL_DATABASE: hellofreshgo
I got the following error:
System.InvalidOperationException: An exception has been raised that is
likely due to a transient failure. Consider enabling transient error
resiliency by adding 'EnableRetryOnFailure()' to the 'UseMySql' call.
---> MySql.Data.MySqlClient.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts. --->
System.AggregateException: One or more errors occurred. (Connection
refused 127.0.0.1:3306)
Before someone ask yes as the error mentions, I already added EnableRetryOnFailure() to UseMySQL()

Communications link failure , Spring Boot + MySql +Docker + Hibernate

I'm working with spring boot, hibernate & MySql. While running the application it is running well as per expectation . But while making the docker-compose file and running the app docker image with mysql docker image it gives this error.
Error
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
java.net.ConnectException: Connection refused.
private Connection createConnection() throws SQLException
{
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
String mysqlUrl = "jdbc:mysql://localhost/database?autoReconnect=true&useSSL=false";
Connection connection = DriverManager.getConnection(mysqlUrl, "root", "root");
return connection;
}
Application.properties
spring.datasource.url=jdbc:mysql://localhost/database?autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
Please guide me how to tackle this.
docker-compose.yml
version: '3'
services:
docker-mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=database
- MYSQL_USER=root
- MYSQL_PASSWORD=root
ports:
- 3307:3306
app:
image: app:latest
ports:
- 8091:8091
depends_on:
- docker-mysql
Issue is due to reference of localhost in the jdbc url.
Below configuration should work.
**docker-compose.yml**
version: '3'
services:
docker-mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=database
- MYSQL_USER=root
- MYSQL_PASSWORD=root
ports:
- 3307:3306
app:
image: app:latest
ports:
- 8091:8091
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://docker-mysql:3306/database?autoReconnect=true&useSSL=false
depends_on:
- docker-mysql
This Docker forum discussion helped me when I was running into this error. For me it was a problem with cache and I didn't get the error after running docker-compose down --rmi all
For me, it was the version of mysql
image: mysql:8 -> image: mysql:5.7
did you tell your docker that it depends on SQL?
I mean is there something like this:
depends_on:
- mysql_server
in your docker-compose.yml ?
looks like a configuration issue.
In my case I have provided proper privilege for my user to get connected from docker host and the error war gone.
I have provided % as host for my user which will provide access to connect from any host. The default root user will only connects from localhost.
Put something like this in the application.properties
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/test
spring.datasource.username=${MYSQL_USER:root}
spring.datasource.password=${MYSQL_PASSWORD:password}

Configure app and MySQL DB in docker-compose.yaml - Could not open JDBC Connection

I configured an app and mysql db within a docker-compose.yaml file below. While both services start, the app cannot open a connection to the DB when an http request is sent. When the app and mysql DB are defined in separate containers, the request succeeds. I am sure it is something simple in the docker compose config.
version: '3.7'
services:
database:
image: mysql:5.7
container_name: docker_test-device-telemetry-mysql
command: --explicit_defaults_for_timestamp
environment:
MYSQL_ROOT_PASSWORD: 12345
MYSQL_ALLOW_EMPTY_PASSWORD: "no"
volumes:
- ./initdb.d:/docker-entrypoint-initdb.d
ports:
- "6603:3306"
device-telemetry:
image: 224713337986.dkr.ecr.eu-west-1.amazonaws.com/device-telemetry:2.5.0
container_name: docker_test-device-telemetry-app
volumes:
- ./application.yaml:/application.yaml
- ./bootstrap.yaml:/bootstrap.yaml
ports:
- "7857:7847"
depends_on:
- database
"timestamp": "2018-10-18T20:46:17.654+0000",
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.transaction.CannotCreateTransactionException",
"message": "Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Cannot create PoolableConnectionFactory (Communications link failure\n\nThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.)",
}
The problem is in the reference to the url containing DB details in the application.yaml
It should be
url: jdbc:mysql://database:3306/local_telemetry
where database is the name of the DB defined in docker-compose.yaml
and not
url: jdbc:mysql://127.0.0.1:3306/local_telemetry