I am trying to connect the container of my springboot application with the container of a mysql image using docker-compose, however when I run docker-compose up
my terminal starts a loop where it starts the spring application, try to connect with the MySQL container, fails and keep trying. The error that I get is com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failures
docker-compose file:
version: '3.8'
services:
mysqldb:
image: mysql
platform: linux/x86_64
env_file: ./.env
restart: always
environment:
- MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD
- MYSQL_DATABASE=$MYSQLDB_DATABASE
ports:
- $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
volumes:
- db:/var/lib/mysql
app:
depends_on:
- mysqldb
build: .
restart: always
env_file: ./.env
ports:
- $APP_LOCAL_PORT:$APP_DOCKER_PORT
environment:
- DB_HOST=mysqldb
- DB_USER=$MYSQLDB_USER
- DB_PASSWORD=$MYSQLDB_ROOT_PASSWORD
- DB_NAME=$MYSQLDB_DATABASE
- DB_PORT=$MYSQLDB_DOCKER_PORT
stdin_open: true
tty: true
volumes:
db:
.env:
MYSQLDB_USER=root
MYSQLDB_ROOT_PASSWORD=12345678
MYSQLDB_DATABASE=dronefeederdb
MYSQLDB_LOCAL_PORT=3306
MYSQLDB_DOCKER_PORT=3306
APP_LOCAL_PORT=8080
APP_DOCKER_PORT=8080
Application.yaml:
server:
port: 8080
spring:
datasource:
username: ${DB_USER}
password: ${DB_PASSWORD}
url: jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}
jpa:
hibernate:
ddl-auto: update
show-sql: true
open-in-view: false
#https://ia-tec-development.medium.com/lombok-e-spring-data-jpa-142398897733
security.user:
name: dronefeeder
password: dronefeeder
#https://www.baeldung.com/spring-boot-security-autoconfiguration
resilience4j.circuitbreaker:
configs:
default:
waitDurationInOpenState: 10s
failureRateThreshold: 10
#instances:
#estudantes:
#baseConfig: default
Dockerfile:
FROM openjdk:11.0-jdk as build-image
WORKDIR /app
COPY . .
RUN ./mvnw clean package -DskipTests
FROM openjdk:11.0-jre
COPY --from=build-image /app/target/*.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/app.jar"]
Repository link: https://github.com/julia-baptista/dronefeeder/tree/docker-configuration
CodePudding user response:
I believe the issue is your application's use of localhost for the SQL URL in the Application.yaml property file. Since your app runs on a container by itself it tries to look at localhost of the container, while your SQL server is in another container, with its own localhost. Localhost in docker container do not refer to the host, they refer to the localhost within the container itself. If you want to access the host machine, this is an excellent answer From inside of a Docker container, how do I connect to the localhost of the machine?
url: jdbc:mysql://localhost:3306/dronefeederdb
localhost should not be used, you need to use the sql continainer url.
The fastest option is to use host.docker.internal
instead of localhost. But its not the best.
Another quick option is to run the two containers on the same docker network. Define that in your compose file the same way as the volumes. Then set each container to that network. See Networking in Compose. Then you can set your SQL url to use the SQL container name instead of localhost. So this..
url: jdbc:mysql://localhost:3306/dronefeederdb
becomes url: jdbc:mysql://mysql/dronefeederdb
Neither option is robust, since you're hardcoding the container name in the application property file. A better solution is to have an environment variable in your webApp image that can accept the URL to the SQL server. Then you can provide the SQL location when running the container, or in your compose file (Environment variables in Compose). This way the SQL server can be anywhere.
CodePudding user response:
You need to add in the app
definition block a depends on:
sentence, to make docker compose to not boot the application until the database is up.
Check this documentation: Docker Compose Startup Order