Hello I am trying to deploy a Spring Boot application using docker-compose. However, while running the file with the docker-compose up -d command, the following error occurred. I have created a project directory inside my EC2 instance, and a docker-compose.yml file exists within that directory. They say it's an issue with the MySQL connection, but I can't figure out what's wrong. The Spring Boot app container is running fine, and I want to deploy my application.
ERROR 1 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : 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. 2025-01-04T21:16:36.993+09:00 WARN 1 --- [ main] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata
org.hibernate.exception.JDBCConnectionException: unable to obtain isolated JDBC connection [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.] [n/a] at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:100) ~[hibernate-core-6.6.4.Final.jar!/:6.6.4.Final] . . . Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
Below are the docker-compose.yml and application.yml files I have written. The actual values have been replaced with 'test'.
//docker-compose.yml
version: "3"
services:
mysql:
image: mysql:8.0
container_name: mysql
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: testdb
MYSQL_ROOT_PASSWORD: testpassword
volumes:
- mysql-vl:/var/lib/mysql
networks:
- test-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
redis:
image: redis:latest
container_name: redis
ports:
- "6379:6379"
volumes:
- redis-vl:/data
networks:
- test-network
app:
image: test/myimage:latest
container_name: test
ports:
- "8080:8080"
environment:
DB_URL: mysql
REDIS_HOST: redis
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
networks:
- test-network
environment:
DB_URL: mysql
REDIS_HOST: redis
volumes:
mysql-vl:
driver: local
redis-vl:
driver: local
networks:
test-network:
driver: bridge
//application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: testpassword
url: jdbc:mysql://${DB_URL:localhost}:3306/testdb?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
jpa:
hibernate:
ddl-auto: update
properties:
show_sql: true
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
data:
redis:
port: 6379
host: ${REDIS_HOST:localhost}
jwt:
secret-key: secretkey
access-exp: 7200000
refresh-exp: 604800000
When I run it afterward, the Redis and MySQL containers start without any issues. Please help me figure out what the problem might be. Please help me!!!!
The DB_URL environment variable is set to mysql, and your application.yml uses it to construct the JDBC URL. This should work because Docker Compose services in the same network can communicate using their service names. However, ensure that The mysql service is running and healthy. The DB_URL environment variable is correctly passed to the container running your Spring Boot app.Add the following environment section to your docker-compose.yml for the app service:
environment:
DB_URL: mysql
REDIS_HOST: redis
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydb?useSSL=false&useUnicode=true&serverTimezone=Asia/Seoul
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: password
Update your application.yml to rely on these environment variables directly:
spring:
datasource:
url: ${SPRING_DATASOURCE_URL}
username: ${SPRING_DATASOURCE_USERNAME}
password: ${SPRING_DATASOURCE_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
The MySQL container may not be ready to accept connections when your Spring Boot application starts, even if the health check passes. Add a startup delay to your application to ensure the database is fully ready before trying to connect. Modify the depends_on section in the docker-compose.yml file to include a condition for MySQL's readiness:
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
Alternatively, you can also use a retry mechanism in your Spring Boot application or an entrypoint script to wait until MySQL is accessible.
The health check for MySQL in your docker-compose.yml checks if MySQL is alive but does not confirm that it is ready to accept connections. Replace the health check with one that waits for MySQL to be fully initialized:
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost --silent"]
interval: 10s
timeout: 20s
retries: 10