Spring Boot + MySQL docker containers - mysql

I have two containers, one with a Srping app and another with mysql. When I run the Spring app on my local machine, it successfully connects to my MySQL db running in a docker container. Once I spin up the Spring container I get a connection error, the app is unable to communicate with the MySQL container. How do I configure the Spring container to communicate with the db container? I've tried creating a bridge network to no avail. I believe my issue is spring.datasource.url=jdbc:mysql://localhost:3309/library but when I try with the network id the jar fails to build spring.datasource.url=jdbc:mysql://lms-network/library. I've been following this tutorial. docker image.

There are couple of ways we can solve it.
Using docker-compose
Put both the containers in docker-compose file. Example:
version: "3"
services:
spring-boot-service:
build:
context: .
ports:
- 8080:8080
environment:
DB_HOST: mysql-db
DB_NAME: library
DB_USER: <user>
DB_PASSWORD : <pwd>
mysql-db:
image: mysql
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: "root"
MYSQL_DATABASE: <db_name>
#... other properties
then in application.properties, use connection string as :
spring.datasource.url=jdbc:mysql://${DB_HOST}:3306/${DB_NAME}
then use docker-compose up to run both containers together. This way they will share network through docker-compose.
Using host.docker.internal
When you run your spring boot app and mysql in separate containers, you can't refer the mysql database from localhost anymore as localhost means pointing to your container. Since mysql is running on your host machine, you can refer it by using host.docker.internal instead of localhost in connection string.
So you connection string should be
spring.datasource.url=jdbc:mysql://host.docker.internal:3309/library

Related

How to connect local mysql(or docker container mysql) from docker container grafana?

I created grafana with a docker container. And I created mysql with docker container. After that, I tried to access grafana and add mysql container via 'data source'. However, the following error occurred. What is the problem?
db query error: query failed - please inspect Grafana server log for details
[grafana's data sources setting]
Host : 10.0.7.35:3306
And I set bind-address at '/etc/mysql/my.cnf' for 0.0.0.0:3306 in mysql container.
You can do it in three ways
You can run docker with MySQL and expose 3306 (by adding -p 3306:3306 port and find IP of docker and connect to that port on that IP from the same network
Expose MySQL port and then run app docker with --link name_of_mysql_container:mysql and then on the app docker just connect to name_of_mysql_container
Use Docker composer create
docker-composer.yml with content similar to:
version: '3.2'
services:
app:
build: .
image: lap
environment:
- DB_HOST=mysql
mysql:
image: mysql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
And then you can use in your app container database connection to host named 'mysql'

How to migrate schema using Flyway into a docker container database to create an isolated testing environment?

I want to migrate the schemas I have for the tables in my db into a docker container I've made. First time using flyway and it seems entirely possible for it to be able to migrate the schema over and into my db. I want to make it so that when I run my unit-tests locally it will run against this docker test container and not the public db.
Here is what I have so far, inside my docker-compose.yaml file:
db:
image: mysql:latest
network_mode: bridge
restart: always
environment:
MYSQL_ROOT_PASSWORD: test
MYSQL_DATABASE: test
ports:
- "3306:3306"
When I run docker-compose up on my terminal, the container appears to build and is shown in the Docker UI. And when I run docker ps in another terminal I see the server is spun up.
Then when I go to MySQL workbench UI and login the credentials for the container as:
Username: localhost
Port: 3306
Password: test
Username: root
And when I run that I get a boiler-plate mysql db. Now what I want to do now is migrate the schema of another db to replace the boiler-plate one.
So I have flyway installed and everything setup on my machine but I don't know how to make the connection between that docker container db I just made and the db schema I have.
Here is my flyway file so far:
flyway.url=jdbc:mysql://localhost:3306/db
flyway.user=root
flyway.password=test
flyway.baselineOnMigrate=false
flyway.defaultSchema=config_data
flyway.schemas=config_data, kol_data, baw_data, ter_data
I also think this layout I found online of the docker-compose.yaml file might work too but not sure how to integrate it into my code"
version: '3'
services:
flyway:
image: flyway/flyway:6.3.1
command: -configFiles=/flyway/conf/flyway.config -locations=filesystem:/flyway/sql -connectRetries=60 migrate
volumes:
- ${PWD}/sql_versions:/flyway/sql
- ${PWD}/docker-flyway.config:/flyway/conf/flyway.config
depends_on:
- postgres
postgres:
image: postgres:12.2
restart: always
ports:
- "5432:5432"
environment:
- POSTGRES_USER=example-username
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=db-name
All in all I simply want to take the schema from one db and put that into my docker container so that I can run unit-tests against it.
Thanks

Docker MySQL - can't connect from Spring Boot app to MySQL database

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;"
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.
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 of 3308
Enjoy
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
Before you try to connect to the Docker container you should stop mysql in your computer then go to the application.properties and type:
spring.datasource.url=jdbc:mysql://localhost:3306/NAME_OF_YOUR_DB_HERE?useSSL=false&allowPublicKeyRetrieval=true
Regarding localhost, you should inspect the mysql container and pick the IP address and use it instead. most likely is 172.17.0.2. If it did not work then use localhost.

Local development with docker compose - Using Mysql localhost

I am a beginner with Docker and docker-compose for local development on my Mac. Currently, if I restart my containers, the MySql data is wiped out.
I would like to enable persistent storage for MySql local development.
Is there a way I can connect my application running inside docker container to the MySql running on my Mac Host machine?
My docker-compose.yaml file:
mysql:
build: ./mysql
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ******
restart: on-failure
ports:
- 3306:3306
Apart from connecting docker application to MySql on local machine, is there any other way to achieve this?
you can solve this problem by using volumes in docker-compose.yaml file. please refer the following links
link1,
link2. whenever a docker container runs, it will map the volume to the container. Syntax for the volumes in docker-compose.yaml is as follows:
volumes:
- <path in host>:<path in container>

How to connect to a MySQL Docker Container via SSH?

When I try to tunnel via SSH to the Host Mashine (vServer) and then try to connect via the internal docker Container-IP then I can't connect to MySQL.
This is my docker-compose file.
version: '2'
services:
mysql:
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: test
volumes:
- ./db:/var/lib/mysql
The only solution I found was to forward the MySQL-Port of the mysql container to the Host-Mashine.
version: '2'
services:
mysql:
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: test
volumes:
- ./db:/var/lib/mysql
ports:
- 3306:3306
Then I am able to connect via the Host IP to MySQL but this is without SSH its direct via TCP and the port.
This is a No-Go for me to bring the MySQL Service into the internet.
Reasons can be found here https://security.stackexchange.com/questions/63881/is-it-not-safe-to-open-mysqls-port-to-the-internet why it is not a good practice to bring your mysql port into the internet.
So what is a good practice to connect to my docker mysql container with SSH but keep the mysql ports closed?
One simple way is to bind the MySQL port only to the localhost address. That assumes the host has a mysql client available outside of Docker.
ports:
- 127.0.0.1:3306:3306
You could also omit the ports section completely (no port binding at all), and use the mysql client that's already inside the container.
docker-compose exec mysql bash
Then run the mysql command inside the container to do whatever queries you want to do.
An easy way to achieve this is to forward the ssh port of the docker conatiner to some port on your host, i.e.
ports:
- 22:<some free host port>
and then access the container via ssh to the host port you used. Note, that it is a bad idea to use port 22, since that will cause a conflict with the ssh server running on your host.