Docker MySQL - can't connect from Spring Boot app to MySQL database
Solution 1
Try this docker-compose.yml
:
version: '3'
services:
workaround-mysql:
container_name: workaround-mysql
image: mysql
environment:
MYSQL_DATABASE: workaround
MYSQL_USER: springuser
MYSQL_PASSWORD: admin
MYSQL_ROOT_PASSWORD: admin
MYSQL_ROOT_HOST: '%'
ports:
- "3308:3306"
restart: always
workaround:
depends_on:
- workaround-mysql
restart: always
# will build ./docker/workaround/Dockerfile
build: ./docker/workaround
working_dir: /workaround
volumes:
- ./:/workaround
- ~/.m2:/root/.m2
expose:
- "8080"
command: "mvn clean spring-boot:run"
And update your application.properties
to use the next JDBC connection url:
spring.datasource.url=jdbc:mysql://workaround-mysql:3306/workaround?serverTimezone=UTC&max_allowed_packet=15728640
It should work when both containers in the same docker-compose file, because docker-compose creates default network for containers, so they can resolve each other by name.
Solution 2
What you haven't tried so far is running both containers on the same Docker network.
First, forget about IP addressing - using it should be avoided by all means.
Second, launch both compose instances with the same Docker network.
Third, do not expose ports - inside bridge network all ports are accessible to running containers.
-
Create global network
docker network create foo
-
Modify both compose files so that they use this network instead of creating each one its own:
version: '3.5' services: .... networks: default: external: true name: foo
-
Remove
expose
directives from compose files - inside one network all ports are exposed by default -
Modify connection strings to use default
3306
port instead of3308
-
Enjoy
Solution 3
In order for the service to connect with MySql through docker it has to be in same network, look into Docker network
But for better solution I would suggest you to write a single docker compose file for MySql and Spring boot.The reason is it will easily be linked when you do that.No need any other configuration.
version: "3"
services:
mysql-service:
image: mysql
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=db
- MYSQL_USER=root
- MYSQL_PASSWORD=pass
- MYSQL_ROOT_PASSWORD=pass
spring-service:
image: springservce:latest
ports:
- "8080:8080"
depends_on:
- mysql-service
Related videos on Youtube
Tomas Bisciak
Java programmer ,CS bachelors degree from the University of Ss. Cyril and Methodius in Trnava. Constantly trying to improve my skills :) I welcome edits to my answers/questions.
Updated on September 27, 2022Comments
-
Tomas Bisciak over 1 year
What I'm trying to do is, connect from my spring-boot app to mysql database in Docker. Each in their own container.
But I must be having something wrong because I can't do it.
To keep it simple :
application-properties :
# URL for the mysql db spring.datasource.url=jdbc:mysql://workaround-mysql:3308/workaround?serverTimezone=UTC&max_allowed_packet=15728640 # User name in mysql spring.datasource.username=springuser # Password for mysql spring.datasource.password=admin #Port at which application runs server.port=8080
docker-compose for MySQL:
version: '3' services: workaround-mysql: container_name: workaround-mysql image: mysql environment: MYSQL_DATABASE: workaround MYSQL_USER: springuser MYSQL_PASSWORD: admin MYSQL_ROOT_PASSWORD: admin MYSQL_ROOT_HOST: '%' ports: - "3308:3306" restart: always
So pretty simple right ? Database I start with
docker-compose up
:All seems to be working fine so far.
Now that I have db started, to the application, this is its
docker-compose.yml
:version: '3' services: workaround: restart: always # will build ./docker/workaround/Dockerfile build: ./docker/workaround working_dir: /workaround volumes: - ./:/workaround - ~/.m2:/root/.m2 expose: - "8080" command: "mvn clean spring-boot:run"
For its
Dockerfile
I use Linux Alpine and Java.FROM alpine:3.9 ....add java... RUN apk update RUN apk add dos2unix --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community/ --allow-untrusted RUN apk add bash RUN apk add maven
Super simple. Now let's start the application :
Unknown host, so let's try the IP then :
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' workaround-mysql # URL for the mysql db spring.datasource.url=jdbc:mysql://172.20.0.2:3308/workaround?serverTimezone=UTC&max_allowed_packet=15728640
Now I get timeout:
As you can see I get error. What is wrong with my setup and how to fix this? Either I have unknown host exception or Refused to connect or connection timeout.
I have tried:
- Using ip of a container in my application.properties, didn't work
- Different ports for MySQL and application
- Different images and versions of MySQL
- Having everything in one docker compose with wait
- timer for database.
- Minimal setup with https://github.com/hellokoding/hellokoding-courses/tree/master/docker-examples/dockercompose-springboot-mysql-nginx Also resulted in communication link failure, Site was accessible but I doubt that db was connected properly.
Notes:
I run this all on one computer I use port 3308 because I have local MySQL db at 3306.
Here is
docker ps -a
@Vusal ANSWER output :
Only thing different from code in answer I did wait for database to be ready 30 seconds
command: /bin/bash -c "sleep 30;mvn clean spring-boot:run;"
-
Tomas Bisciak almost 5 years@M.Deinum Still getting error Connection refused even when they are on same network
-
Tomas Bisciak almost 5 yearsI will try it out
-
Tomas Bisciak almost 5 yearsWill try it out
-
Tomas Bisciak almost 5 yearsBud if i remove use of 3308 I will clash with 3306 that i have running locally already (mysql database) that i test with from intellij ? Right?
-
Tomas Bisciak almost 5 yearsservices.workaround-mysql.networks.default contains unsupported option: 'external' and services.workaround-mysql.networks.default contains unsupported option: 'name'
-
grapes almost 5 yearsPut
version: '3.5'
or later at the top of yaml files -
grapes almost 5 years"Bud if i remove use of 3308 I will clash with 3306 that i have running locally already (mysql database) that i test with from intellij ? Right?" No, you wont.
3306
will exist only inside networkfoo
and will NOT be available outside. As far as I understood, you connect to db from another container, not from host. If I am wrong and you also need to connect from host, you will need to expose ports -
Tomas Bisciak almost 5 yearsOk so after I have used code you send me , I have Caused by: java.net.ConnectException: Connection refused (Connection refused) I already had that before when i tried this approach. No success, Will update question with full output
-
Tomas Bisciak almost 5 yearsUpdated question with output to your answer.
-
Tomas Bisciak almost 5 yearsTried version 3.5 and 3.7 still getting unsupported option on external keyword (when i do docker-compose build)
-
grapes almost 5 years
docker-compose --version
? -
Tomas Bisciak almost 5 yearsdocker-compose version 1.23.2, build 1110ad01
-
Avi almost 5 yearsThe jdbc url in application.properties should be something like this "url=jdbc:mysql://mysql-service:3306/db" (In docke-compse.yml, I have mentioned my service name as 'mysql-service' and DB name as 'db' that's why have used the same value in the URL ).Same goes for username and password
-
Tomas Bisciak almost 5 yearsI will test since i still used that 3308 , I will change it to 3306 and see if it changes from connection refused
-
Avi almost 5 years@TomasBisciak, for you reference github.com/aviu95/user_mgt look into the code
-
Tomas Bisciak almost 5 yearsYes i made it work! Your answer was pretty close to what accepted answer is . Pretty much same, so thank you so much also!!
-
grapes almost 5 yearsI've double checked this syntax, can you verify you have no misspellings and correct tabulation? Note -
networks
directive is GLOBAL, not related to any particular service -
Tomas Bisciak almost 5 yearsMy fault didnt have it global ;) I have put it under service so that might be the case .Either way problem is solved by info in your answer will probably be used to further refine what i have now :D awesome