Docker compose. Networks. Spring Boot and MySQL connection - mysql

I try to connect spring boot web app to database container.
And I can ping db container from web. But web can't connect to db by exposed 3307 port. But I can connect to db by internal container port 3306. Project very simple. What is may wrong?
This is my docker-compose.yml:
version: '3'
services:
db:
build:
context: ./db
dockerfile: Dockerfile
image: db
ports:
- "3307:3306"
volumes:
- demo_volume:/var/lib/mysql
networks:
- my-backend
web:
build:
context: ./web
dockerfile: Dockerfile
image: web
depends_on:
- db
ports:
- "18080:8080"
networks:
- my-backend
environment:
- DATABASE_HOST=db
- DATABASE_USER=user
- DATABASE_PASSWORD=password
- DATABASE_NAME=demo
- DATABASE_PORT=3307
- SPRING_PROFILES_ACTIVE=container
- DEBUG=true
volumes:
demo_volume:
driver: local
networks:
my-backend:
driver: bridge
It's simple enough.
My application.yml for active profile - container
spring:
profiles:
container
datasource:
url: jdbc:mysql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?characterEncoding=UTF-8
username: ${DATABASE_USER}
password: ${DATABASE_PASSWORD}
driver-class-name: com.mysql.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQLDialect
Also very simple
db Dockerfile:
FROM mysql:5.7
ENV MYSQL_ROOT_PASSWORD=admin
ENV MYSQL_DATABASE=demo
ENV MYSQL_USER=user
ENV MYSQL_PASSWORD=password
ADD dump.sql /docker-entrypoint-initdb.d/
And web Dockerfile:
FROM java:8-jre
COPY ./web.jar /app/web.jar
CMD ["java", "-jar", "/app/web.jar"]
CMD ["java", "-Xmx200m", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/web.jar"]

Regarding Docker documentation all containers in the same bridge network (user defined) communicates via their internal ports. It's explained with image isolated_bridge_network
If you desire your containers should be available from external network you should publish ports for this one. Publish - means you should map internal ports to external environment. See on image
published_ports_from_isolated_bridge_network

You should link the Container to make it work.
web:
build:
context: ./web
dockerfile: Dockerfile
image: web
depends_on:
- db
ports:
- "18080:8080"
networks:
- my-backend
environment:
- DATABASE_HOST=db
- DATABASE_USER=user
- DATABASE_PASSWORD=password
- DATABASE_NAME=demo
- DATABASE_PORT=3307
- SPRING_PROFILES_ACTIVE=container
- DEBUG=true
links:
- db
Now inside your web Container /etc/hosts should have an entry for db Container

Related

Can't connect to mysql docker container from springboot docker container

I want to connect from the sprinboot container to the mysql container but i get this error:
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
I am using docker-compose.
This is my docker-compose file:
version: '3'
services:
trips-db:
image: "mysql"
container_name: "trips-db"
volumes:
- newDatabase:/home/sharedData
ports:
- 49152:3306
environment:
- MYSQL_USER=adham
- MYSQL_PASSWORD=123
- MYSQL_ROOT_PASSWORD=admin
trips-app:
build: ./Wasalny_BE
container_name: trips-app
ports:
- 8080:8080
links:
- trips-db
volumes:
newDatabase:
This is my spring boot docker file:
FROM openjdk:8-jdk-alpine
COPY target/wasalny-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
This is my application.properties file:
spring.datasource.url= jdbc:mysql://trips-db:49152/wslny?allowPublicKeyRetrieval=true&useSSL=false&createDatabaseIfNotExist=true
spring.datasource.username= root
spring.datasource.password= admin
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto= update
I run using the following command form the terminal:
docker-compose up -d
--force-recreate
Please create a docker network and attach it into the compose file.
Create a docker Network first like below.
docker network create ext-network
Add network settings into your yaml file as below and give a try
version: '3'
services:
trips-db:
image: "mysql"
container_name: "trips-db"
volumes:
- newDatabase:/home/sharedData
ports:
- 49152:3306
networks:
- ext-network
environment:
- MYSQL_USER=adham
- MYSQL_PASSWORD=123
- MYSQL_ROOT_PASSWORD=admin
trips-app:
build: ./Wasalny_BE
container_name: trips-app
ports:
- 8080:8080
networks:
- ext-network
links:
- trips-db
networks:
ext-network:
external: true
volumes:
newDatabase:

Communication link failure. Docker-compose, Spring boot, MySQL

I'm having a problem in connection between my application to DB (in-spite of similarity)
Dockerfile:
FROM openjdk:8
ADD target/DockerMyBlog.jar DockerMyBlog.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "DockerMyBlog.jar"]
docker-compose.yml
version: "3"
services:
app-db:
image: mysql:latest
container_name: "my_db"
environment:
- MYSQL_ROOT_PASSWORD=hey
- MYSQL_DATABASE=javastudy
- MYSQL_USER=roman
- MYSQL_PASSWORD=hey
ports:
- 3306:3306
app:
build: .
container_name: "my_app"
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://app-db:3306/javastudy?autoReconnect=true&useSSL=false
depends_on:
- app-db
Instead of "build: ." tried "image: dockermyblog:latest". No result.
application.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/javastudy
jdbc.username=roman
jdbc.password=hey
my_db is working. After "exec" I can create required tables in it. But can't launch my_app because of "Communication link failure".
What's wrong in my yml??
My guess is that 'localhost' is not a valid enpoint for a Docker container talking to another container running on the host in your application.properties. You can try and put it on IP address of the machine like so:
jdbc.url=jdbc:mysql://192.168.1.100:3306/javastudy
or
jdbc.url=jdbc:mysql://host.docker.internal:3306/javastudy

Spring Boot + MySQL + Docker Compose - Cannot make Spring Boot connect to MySQL

I've been trying to set up a connection between a backend (runs on Spring Boot) container and a pre-built MySQL container. However, I cannot get it to connect. My docker compose file is:
version: '3.7'
services:
test-mysql:
image: mysql
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: root
backend:
depends_on:
- test-mysql
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
volumes:
db_data: {}
my application.properties:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url=jdbc:mysql://test-mysql:3306/testdb?autoReconnect=true&failOverReadOnly=false&maxReconnects=10
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=test
spring.datasource.password=test
When I use docker-compose up, Spring Boot is not able to recognize the container name test-mysql. It throws: java.net.UnknownHostException
When I change it to an IP, it says connection refused. I have been looking everywhere and couldn't come with a fix. I hope anyone can help me out. Thank you!
You have to mention the backend mysql properties in the composer file like below,
backend:
depends_on:
- test-mysql
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://test-
mysql:3306/testdbautoReconnect=true&failOverReadOnly=false&maxReconnects=10
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
links:
- test-mysql:test-mysql
If this wouldn't work try to create a common docker network and add it to your composer file like below,
backend:
depends_on:
- test-mysql
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
restart: always
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://test-
mysql:3306/testdbautoReconnect=true&failOverReadOnly=false&maxReconnects=10
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
networks:
-common-network
test-mysql:
image: mysql
restart: always
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: root
networks:
-common-network
#Docker Networks
networks:
common-network:
driver: bridge
#Volumes
volumes:
dbdata:
driver: local
You can define a common network on which both the application server and the database can connect. Please check the file (docker-compose.yml) below where I have defined a common network: backend
# Docker Compose file Reference (https://docs.docker.com/compose/compose-file/)
version: '3.7'
# Define services
services:
# App backend service
app-server:
# Configuration for building the docker image for the backend service
build:
context: . # Use an image built from the specified dockerfile in the `springboot-app-server` directory.
dockerfile: Dockerfile
ports:
- "8080:8080" # Forward the exposed port 4000 on the container to port 4000 on the host machine
restart: always
depends_on:
- db # This service depends on mysql. Start that first.
environment: # Pass environment variables to the service
SPRING_DATASOURCE_URL: jdbc:mysql://test-mysql:3306/testdb?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
SPRING_DATASOURCE_USERNAME: test
SPRING_DATASOURCE_PASSWORD: test
networks: # Networks to join (Services on the same network can communicate with each other using their name)
- backend
# Database Service (Mysql)
db:
image: mysql:5.7
ports:
- "3306:3306"
restart: always
environment:
MYSQL_DATABASE: testdb
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: root
volumes:
- db-data:/var/lib/mysql
networks:
- backend
# Volumes
volumes:
db-data:
# Networks to be created to facilitate communication between containers
networks:
backend:
I have written a blog and a simple working Spring Boot MySQL application on GitHub which tells about using Docker Compose. Please check: http://softwaredevelopercentral.blogspot.com/2020/10/spring-boot-mysql-docker-compose-example.html
If you would like to use this test-mysql in your spring config
spring.datasource.url=jdbc:mysql://test-mysql:3306/testdb?autoReconnect=true&failOverReadOnly=false&maxReconnects=10
Then add the hostname attribute at service test-mysql
version: '3.7'
services:
test-mysql:
image: mysql
hostname: test-mysql
...
I hope this has been already solved but in case it hasn't yet, the problem lies in mysql docker container lagging behind the start up.
Another problem is that you might need to build the jar file and then copy it the container. That's a big problem because when you build the jar file, the database with db as hostname is unavailable. So when you are building the jar file, skip the test.
This is bash script i created but you can run command one by one:
#!/bin/bash
cd storage-service
rm -rf target/
mvn clean compile package -Dmaven.test.skip=true
cd ..
docker-compose up
In case you want to initialize db in the container. That file is in the folder env where i have a file database.env
-- create the databases
CREATE DATABASE IF NOT EXISTS model_storage;
-- create the users for each database
CREATE USER 'arsene'#'localhost' IDENTIFIED BY 'arsene';
GRANT CREATE, ALTER, INDEX, LOCK TABLES, REFERENCES, UPDATE, DELETE, DROP, SELECT, INSERT ON `model_storage`.* TO 'arsene'#'localhost';
FLUSH PRIVILEGES;
The backend service Dockerfile looks like this:
FROM adoptopenjdk/openjdk11
COPY target/*.jar storage.jar
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /storage.jar" ]
EXPOSE 8089
The database env file looks like this:
MYSQL_ROOT_PASSWORD=arsene
MYSQL_DATABASE=model_storage
MYSQL_USER=arsene
MYSQL_PASSWORD=arsene
DATABASE_HOST=model_storage
DATABASE_USER=arsene
DATABASE_PASSWORD=arsene
DATABASE_NAME=model_storage
DATABASE_PORT=3306
In case you intend to pass JAVA_OPTS env in the image. These can be used later as seen in docker-compose.yml below
Your backend (the service that depends on the mysql db) needs to restart until the docker-compose is able to resolve the the container name of mysql, in my case its name is db. And don't forget to include datasource connection properties in docker-compose backend service image as i did below. I am not an expert in spring boot and neither in docker but for now it works!
Below is the way mine is structured:
I am using docker version: "3.8"
Storage service
storage-service:
container_name: storage-service
restart: always
build:
context: storage-service
image: "service_storage_image"
depends_on:
- db
ports:
- "8089:8089"
links:
- db
env_file:
- env/database.env
environment:
WAIT_HOSTS: db:3306
SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/model_storage?allowPublicKeyRetrieval=true&useSSL=false
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: arsene
healthcheck:
test: "/usr/bin/mysql --user=arsene --password=arsene--execute \"SHOW DATABASES;\""
interval: 2s
timeout: 20s
retries: 10
environment:
- JAVA_OPTS=
-DEUREKA_SERVER=http://eureka-registry-server:7070/eureka
-DZIPKIN_SERVER=http://zipkin:9411/
networks:
- private-network-mms
My db in docker-compose is structured this way:
Mysql database
db:
hostname: db
container_name: db
image: "mysql:latest"
env_file:
- env/database.env
volumes:
- type: bind
source: ./env/setup.sql
target: /docker-entrypoint-initdb.d/setup.sql
- db_volume:/var/lib/mysql
ports:
- 3307:3306
networks:
- private-network-mms

Spring Boot MySQL Docker Caused by: java.net.ConnectException: Connection refused (Connection refused)

As in the title:
Caused by: java.net.ConnectException: Connection refused (Connection refused)
This worked for me sometime ago but now unfortunately not.
Script that I execute contains:
mvn clean install -> docker-compose build -> docker-compose up
Dockerfile:
FROM openjdk:8
ADD target/grades.jar grades.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "grades.jar"]
docker-compose.yaml
version: '3'
services:
mysql-standalone:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=grades
- MYSQL_USER=root
- MYSQL_PASSWORD=password
ports:
- "33061:3306"
volumes:
- /data/mysql
grades:
image: grades
build:
context: ./
dockerfile: Dockerfile
depends_on:
- mysql-standalone
ports:
- 8080:8080
volumes:
- /data/grades
And application.properties:
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB:aws_eb_db}
spring.datasource.username=${MYSQL_USERNAME:root}
spring.datasource.password=${MYSQL_PASSWORD:password}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
localhost for you Docker container is not the localhost of the host machine (the one where your Docker containers live). Basically it points to your Docker container itself, where MySQL doesn't live. So you have to point to your MySQL instance, or the host for your containers, as you are mapping the 3306 port of your MySQL to your host's 3306 port.
I would definitely point to the MySQL itself as #LinPy suggested:
spring.datasource.url=jdbc:mysql://mysql-standalone:3306/grades
This should help somebody.
Make sure to run the command below to invalidate the current image:
docker rmi -f <your image id>
version: '3.1'
services:
db:
image: mariadb:10.5.5
restart: always
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=softeasydb
- MYSQL_USER=root
- MYSQL_PASSWORD=root
volumes:
- ./db:/var/lib/mysql
ports:
- 3306:3306
networks:
- common-network
adminer:
image: adminer
restart: always
ports:
- 8080:8080
networks:
- common-network
api-users:
build: .
depends_on:
- db
ports:
- 9090:9090
environment:
- SPRING_PROFILES_ACTIVE=docker
- DATABASE_HOST=db
- DATABASE_USER=root
- DATABASE_PASSWORD=root
- DATABASE_NAME=softeasydb
- DATABASE_PORT=3306
- SERVER_PORT=9090
restart: always
networks:
- common-network
networks:
common-network:
driver: bridge
In your docker-compose.yaml you have a typo in the port mappings for the mysql-standalone container, you need to change the following:
ports:
- "33061:3306"
to
ports:
- "3306:3306"

docker compose spring boot logs

I'm trying to run both a spring boot app and mysql in separate docker containers and I'm having trouble debugging issues because I can't see any logs. When I run docker-compose up I see the start up logs (Spring Boot banner) and see the app start, but after that no more logging. I'm getting a 404 hitting one of my end points but I can't debug it without seeing the logs.
docker-compose.yml:
version: "3.3"
services:
database:
build:
context: ./database
image: pensionator_db
# set default mysql root password, change as needed
environment:
MYSQL_USER: pensionatoruser
MYSQL_DATABASE: pensionatordb
# Expose port 3306 to host. Not for the application but
# handy to inspect the database from the host machine.
ports:
- "3306:3306"
restart: always
appserver:
build:
context: .
dockerfile: app/src/main/docker/Dockerfile
image: pensionator_app
# mount point for application in tomcat
# open ports for tomcat and remote debugging
ports:
- "8080:8080"
- "8000:8000"
restart: always
How do I get logging to work?
There was nothing wrong with the logging, the issue was with my docker-compose.yml file. I needed to link the database correctly.
docker-compose.yml:
version: '3'
services:
database:
image: mysql:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
MYSQL_USER: root
MYSQL_DATABASE: pensionator
ports:
- '3307:3306'
restart: always
appserver:
build:
context: .
dockerfile: src/main/docker/Dockerfile
depends_on:
- database
image: pensionator_app
environment:
SPRING_DATASOURCE_URL: 'jdbc:mysql://database:3306/pensionator'
links:
- database
ports:
- '8080:8080'
- '8000:8000'
restart: always