Below is my docker-compose file and my application.yml file. I am overriding the mysql jdbc url in the docker-compose file.
Why i run via the command line I am able to connect to the database running on docker instance.
mysql -uroot -proot -h127.0.0.1 -P3309
When I execute docker-compose up, i am getting the below error . Spring boot docker instance is not able to connect to the docker instance of mysqldb. Can you please help me understand what could be the issue?
reco-tracker-docker_1 | Caused by: java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, "jdbc:mysql://mysqldb-docker:3309/reco-tracker-dev"
reco-tracker-docker_1 | at com.zaxxer.hikari.util.DriverDataSource.<init>(DriverDataSource.java:110) ~[HikariCP-4.0.3.jar!/:na]
reco-tracker-docker_1 | at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:331) ~[HikariCP-4.0.3.jar!/:na]
reco-tracker-docker_1 | at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:114) ~[HikariCP-4.0.3.jar!/:na]
docker-compose.yml
version: '3.8'
services:
mysqldb-docker:
image: 'mysql:8.0.27'
restart: 'unless-stopped'
ports:
- "3309:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_PASSWORD=root
- MYSQL_DATABASE=reco-tracker-dev
env_file:
- ./.env
volumes:
- mysqldb:/var/lib/mysql
reco-tracker-docker:
image: 'reco-tracker-docker:latest'
ports:
- "8083:8083"
environment:
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root
- SPRING_DATASOURCE_URL="jdbc:mysql://mysqldb-docker:3309/reco-tracker-dev"
depends_on: [mysqldb-docker]
volumes:
mysqldb:
application.yml
server:
port: 8083
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/reco-tracker
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
generate-ddl: true
show-sql: true
database-platform: org.hibernate.dialect.MySQL8Dialect
===============================
UPDATE
Post my discussion in the comments section with [#the-fool],
I modified the files so that the host and container ports for mysql db are same, that avoids any confusion.
I also updated the spring datasource url to be passed from environments even though it was overriding the one already there in application.yml.
I removed the images and volumes using "docker-compose down --rmi all" so that it deletes the containers and the volumes. (I had mapped a different volume before and that was causing issues with mysqldb creating the database)
IT WORKS NOW!!!
application.yml
server:
port: 8083
spring:
datasource:
username: root
password: root
url: ${SPRING_DATASOURCE_URL}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
generate-ddl: true
show-sql: true
database-platform: org.hibernate.dialect.MySQL8Dialect
Dockerfile.yml
FROM openjdk:17
ARG JAR_FILE="*.jar"
COPY target/${JAR_FILE} reco-tracker.jar
EXPOSE 8083
ENTRYPOINT ["java", "-jar","reco-tracker.jar"]
docker-compose.yml
version: '3.8'
services:
mysqldb-docker:
image: 'mysql:8.0.27'
restart: 'unless-stopped'
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_PASSWORD=root
- MYSQL_DATABASE=reco-tracker
volumes:
- mysqldb:/var/lib/mysql
reco-tracker-docker:
image: 'reco-tracker-app:v2'
ports:
- "8083:8083"
environment:
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root
- SPRING_DATASOURCE_URL=jdbc:mysql://mysqldb-docker:3306/reco-tracker
depends_on: [mysqldb-docker]
volumes:
mysqldb:
Your problem is that you are trying to access the DB on the published port. You are using 3009 of the mapping 3309:3306. This does not work. You cannot change the port of a container inside the network. You need to use 3306 if you want to connect over the docker network. 3309 is only available from the host system.
At least in this part it seems to be wrong. (It also seems there could be an issue with the double quotes, I would quote the full string or not all.)
environment:
- SPRING_DATASOURCE_URL="jdbc:mysql://mysqldb-docker:3309/reco-tracker-dev"
In your spring config you are using the right port but there you are using localhost as db host, which also seems wrong.
spring:
datasource:
url: jdbc:mysql://localhost:3306/reco-tracker
I don't know java much, so I cannot tell you how it would behave. If the former env var will overwrite this. But as it stands, both settings are slightly incorrect.
I can imagine that you could fix it by doing something like this.
environment:
# fix the port here
SPRING_DATASOURCE_URL: jdbc:mysql://mysqldb-docker:3306/reco-tracker-dev
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
spring:
datasource:
# Use the env vars in the spring config
url: ${SPRING_DATASOURCE_URL}
username: ${SPRING_DATASOURCE_USERNAME}
password: ${SPRING_DATASOURCE_PASSWORD}
Also make sure that your database namings are consistent. They seem a bit inconsistent in your post. Keep in mind that the name was used the first time the mysql container was started, is stored in the volume. So either use the name you have used at that point in time, or delete the volume to let it create a new database, which will cause you to lose the stored data. So be careful what option you choose.
Have you tried docker "networks" here? If not, then create one network and run the container in same networks.
in yaml, something like:
networks:
-myNet
Related
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`
I have dockerized MySQL which runs on port 3307, there is all configuration on docker-compose file:
version: '3.9'
services:
db:
container_name: mysql
image: mysql:5.7
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=my_user
- MYSQL_PASSWORD=user_pass
- MYSQL_DATABASE=my_db
ports:
- "127.0.0.1:3307:3306"
volumes:
- mysql:/var/lib/mysql
But problem is that the Spring app is running outside of the Docker and when I run my application I've got error:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
And there is also configuration of connection with db on application.yml file:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3307/my_db?serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none
database-platform: org.hibernate.dialect.MySQL5Dialect
I also tried expose ports without 127.0.0.1 and connect by localhost but this doesn't work.
I’m on Mac OS Big Sur and running the following Docker versions
$ docker -v
Docker version 20.10.12, build e91ed57
$ docker-compose -v
Docker Compose version v2.2.3
I’m running a Rails 6 app, whose database is configured like so
development:
adapter: mysql2
encoding: utf8
host: host.docker.internal
database: cfs
pool: 5
username: myuser
password: bypass
I have to use “host.docker.internal” so that the Rails app can access the Docker db when running inside of Docker, set up in my docker-compose.yml like so
services:
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
volumes:
- ./docker/provision/mysql/init:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: bypass
ports:
# <Port exposed> : < MySQL Port running inside container>
- '3306:3306'
expose:
# Opens port 3306 on the container
- '3306'
…
web:
#restart: always
build: ./my-project
ports:
- "3000:3000"
expose:
- '3000'
command: foreman start
volumes:
- ./my-project/:/app
depends_on:
- db
However if I run the app locally without Docker, I have to change my config files to remove “host.docker.internal” and use “127.0.0.1” instead (or localhost).
Is there a way I can set things up so that I have a single database config file that works in both Docker and without Docker such that I don’t have to change the host around?
You can use ERB markup in the database.yml file, which lets you use an environment variable here. In general I'd suggest making default values for things be whatever default will work in a plain non-Docker development environment.
# config/database.yml
development:
host: <%= ENV['DATABASE_HOST'] || 'localhost' %>
If you're running this in a setup where the database hostname isn't localhost – it's in a sibling container, or you're using a cloud-hosted database like Amazon RDS – you can set that environment variable.
# docker-compose.yml
version: '3.8'
services:
db:
image: 'mysql:5.7'
et: cetera
web:
build: .
ports:
- '3000:3000'
depends_on:
- db
environment:
DATABASE_HOST: db # <-- will be read in database.yml
I'm having trouble connecting my spring application with the MySQL database.
In particular, I report the code of the docker compose, the docker file, application.yml and the error log.
docker-compose:
version: '3.3'
services:
my-sql-db:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=user
- MYSQL_USER=user
- MYSQL_DATABASE=spring-app
ports:
- "3306:3306"
customerservice:
image: customer-service
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
depends_on:
- my-sql-db
environment:
SPRING_PROFILES_ACTIVE: MySQLdocker
Dockerfile:
FROM maven:3.6.3-jdk-8
COPY ./ ./
RUN mvn clean package
EXPOSE 8080
CMD ["java", "-jar", "target/my-spring-project-0.0.1-SNAPSHOT.jar"]
Application.yml:
spring:
jpa:
open-in-view: false #per levare warnig OpenSessionInView
properties:
hibernate:
jdbc:
time_zone: CET
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: none
datasource:
url: jdbc:mysql://my-sql-db:3306/spring-app?createDatabaseIfNotExist=true
username: user
password: user
config:
activate:
on-profile: MySQLdocker
Executing the command "docker-compose up -d" the output error is:
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:174) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
I'm not seeing MYSQL_PASSWORD defined in your docker-compose file.
Generally, the error suggests the app cannot connect to MySQL at all. When you have such a problem that could be caused by many things, you should try and narrow it down. Check if the DB is up and running. If yes, then try to connect to it from some MySQL client. And so on, until you figure out what exactly went wrong or at least come up with a more specific question.
I am about to finish my spring boot project.
However, the deployment with docker-compose is just painfully not working
Below is my codes
docker-compose.yml
version: '3'
services:
ibin-db:
container_name: ibin-db
image: mysql:5.7
environment:
MYSQL_DATABASE: iBinApiDB
MYSQL_ROOT_PASSWORD: root
MYSQL_ROOT_HOST: '%'
ports:
- 3306:3306
ibin-inplay:
image: openjdk:14
volumes:
- ./run.sh:/home/ibin/run.sh
- ./ibin-inplay/build/libs:/home/ibin/libs
ports:
- 8001:8080
- 16100:16100
networks:
vpcbr:
ipv4_address: 192.168.219.69
depends_on:
- ibin-db
command: bash -c "cd /home/ibin && sh run.sh"
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 192.168.219.0/24
application.yml
spring:
datasource:
url: jdbc:mysql://ibin-db:3306/iBinApiDB?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
database-platform: org.hibernate.dialect.MySQL5Dialect
generate-ddl: true
didn't miss to run ./gradlew bootJar
However, error pops up no matter what.
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
please help me figure this out.
The two containers aren't on the same Docker-internal network, so they can't see each other. The ibin-inplay container is explicitly assigned to the vpcbr network; the ibin-db container doesn't have any manual networks: configuration, so Compose assigns it to a default network. Networking in Compose describes what Compose will automatically create for you.
You shouldn't need to manually assign IP address to containers or otherwise do manual network configuration in Docker. I'd recommend deleting all of the networks: blocks in the whole file (both the top-level block and the one for the ibin-inplay container) and using the default network everywhere.