skip to Main Content

I am trying to docrize an application of spring boot which also utilizes a mysql db also
Below is the docker file

FROM maven:3.8.3-openjdk-17 AS build
EXPOSE 8081
ADD /target/oks-0.0.1-SNAPSHOT.jar oks-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java","-jar","oks-0.0.1-SNAPSHOT.jar"]

The application-develop.properties is below

spring.datasource.url=jdbc:mysql://localhosts:3306/oks?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password = roots
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
server.port= 8081

Docker compose file

version: "3.7"
services:
  mysql:
    image: mysql:5.6.33
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: roots
      MYSQL_DATABASE: oks
  api_service:
    build: ./oks-api
    ports:
      - 8081:8081
    depends_on:
      - mysql
    environment:
      spring.datasource.url: jdbc:mysql://mysql/oks?characterEncoding=UTF-8
      spring.datasource.username: root
      spring.datasource.password: roots

and below is the error I am facing

compose-api_service-1  |        ... 59 common frames omitted
compose-api_service-1  | Caused by: java.net.ConnectException: Connection refused
compose-api_service-1  |        at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
compose-api_service-1  |        at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na]
compose-api_service-1  |        at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na]
compose-api_service-1  |        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597) ~[na:na]
compose-api_service-1  |        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
compose-api_service-1  |        at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na]
compose-api_service-1  |        at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:153) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
compose-api_service-1  |        at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:62) ~[mysql-connector-j-8.3.0.jar!/:8.3.0]
compose-api_service-1  |        ... 62 common frames omitted
compose-api_service-1  |
compose-api_service-1 exited with code 1

I have tried couple of methods but I am failing , Thank you in advance

2

Answers


  1. Try add spring.host= in your application-develop.properties. Because i think since you have not used network_mode: host in docker it might not find the target to connect.

    Login or Signup to reply.
  2. There are a couple of potential issues here.

    I’d suggest modifying your docker-compose.yml file to something like this:

    version: "3.7"
    services:
      mysql:
        image: mysql:5.6.33
        ports:
          - "3306:3306"
        environment:
          MYSQL_ROOT_PASSWORD: roots
          MYSQL_DATABASE: oks
        healthcheck:
          test: ["CMD", "mysqladmin", "ping"]
          interval: 10s
          timeout: 5s
          retries: 5
          start_period: 30s
    
      api_service:
        build: ./oks-api
        ports:
          - 8081:8081
        depends_on:
          mysql:
            condition: service_healthy
        environment:
          SPRING_DATASOURCE_URL: jdbc:mysql://mysql/oks?characterEncoding=UTF-8
          SPRING_DATASOURCE_USERNAME: root
          SPRING_DATASOURCE_PASSWORD: roots
    

    I have renamed the environment variables in the api_service service.

    I also added a health check to the mysql service, so that it will only be marked as healthy once it is ready to accept connections. The api_service service will not start until the mysql service is healthy.

    This is what the Java connection code might look like, pulling in the details of the database from the environment variables.

    package com.example.demo.config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    import org.springframework.stereotype.Component;
    
    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.ResultSet;
    
    @Configuration
    public class DatabaseConfig {
        private static final Logger logger = LoggerFactory.getLogger(DatabaseConfig.class);
    
        @Value("${SPRING_DATASOURCE_URL}")
        private String dbUrl;
    
        @Value("${SPRING_DATASOURCE_USERNAME}")
        private String dbUsername;
    
        @Value("${SPRING_DATASOURCE_PASSWORD}")
        private String dbPassword;
    
        // DataSource bean configuration
        @Bean
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setUrl(dbUrl);
            dataSource.setUsername(dbUsername);
            dataSource.setPassword(dbPassword);
            return dataSource;
        }
    
        @Component
        public static class MySqlConnectionCheck implements CommandLineRunner {
    
            private final DataSource dataSource;
    
            public MySqlConnectionCheck(DataSource dataSource) {
                this.dataSource = dataSource;
            }
    
            @Override
            public void run(String... args) {
                logger.info("Making connection to MySQL database.");
                try (Connection connection = dataSource.getConnection()) {
                    String query = "SELECT 1";
                    ResultSet rs = connection.createStatement().executeQuery(query);
                    if (rs.next()) {
                        int result = rs.getInt(1);
                        logger.info("🟢 Connected to MySQL database. Test query result: {}", result);
                    }
                } catch (Exception e) {
                    logger.error("❌ Error connecting to MySQL database: ", e);
                }
            }
        }
    }
    

    My impression is that it you are giving the database details as environment variables then you should not duplicate them in your application properties file. One location or the other but not both.

    The layout of the simple application I used for testing is:

    ├── docker-compose.yml
    └── oks-api
        ├── Dockerfile
        ├── pom.xml
        └── src
            └── main
                └── java
                    └── com
                        └── example
                            └── demo
                                ├── config
                                │   └── DatabaseConfig.java
                                └── DemoApplication.java
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search