1

I am using spring-boot to run my microservice on docker which is using MySQL, but my app is not able to make the connection with MySQL

The exception is :

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
app_1  |    at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
app_1  |    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
app_1  |    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)
app_1  |    at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)
app_1  |    at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)
app_1  |    at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:197)
app_1  |    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:121)
app_1  |    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358)
app_1  |    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206)
app_1  |    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477)
app_1  |    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:560)
app_1  |    ... 69 more
app_1  | Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
app_1  | 
app_1  | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
app_1  |    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
app_1  |    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
app_1  |    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
app_1  |    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
app_1  |    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
app_1  |    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
app_1  |    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
app_1  |    at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
app_1  |    at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:91)
app_1  |    at com.mysql.cj.NativeSession.connect(NativeSession.java:144)
app_1  |    at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:956)
app_1  |    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826)
app_1  |    ... 77 more
app_1  | Caused by: java.net.ConnectException: Connection refused (Connection refused)
app_1  |    at java.net.PlainSocketImpl.socketConnect(Native Method)
app_1  |    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
app_1  |    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
app_1  |    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
app_1  |    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
app_1  |    at java.net.Socket.connect(Socket.java:589)
app_1  |    at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:155)
app_1  |    at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:65)
app_1  |    ... 80 more

the docker-compose file is :

version: '3'

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      - MYSQL_DATABASE=inward
      # So you don't have to use root, but you can if you like
      - MYSQL_USER=root
      # You can use whatever password you like
      - MYSQL_PASSWORD=unroot
      # Password for root access
      - MYSQL_ROOT_PASSWORD=unroot
    ports:
      # <Port exposed> : < MySQL Port running inside container>
      - 3307:3306

  app:
    build:
      context: ./
      dockerfile: Dockerfile
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/inward?allowPublicKeyRetrieval=true&useSSL=false
    depends_on:
      - db
    working_dir: /app
    command: [sh, -c, 'mkdir -p ~/logs/; cd /src ; mvn clean spring-boot:run -Dspring.profiles.active=dev -DLOG_DIR=/root/logs/ -DLOG_FILE=hubstamper.log']
    ports:
      - "8080:8080"
    volumes:
      - "${HOME}/.m2:/root/.m2"

Dockerfiule

FROM maven:3.5-jdk-8-alpine
COPY . /app

and application.properties file is :

jdbcUrl=jdbc:mysql://db:3306/inward?allowPublicKeyRetrieval=true&useSSL=false
dataSource.user=root
dataSource.password=unroot
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048
driverClassName=com.mysql.jdbc.Driver
dataSource.driverClassName=com.mysql.jdbc.Driver

I have tried the solution mentioned in the link : Communications link failure , Spring Boot + MySql +Docker + Hibernate

any help will be higly appriciable.

Anshul Sharma
  • 1,018
  • 3
  • 17
  • 39
  • I have tried that as well, I mean using **jdbcUrl=jdbc:mysql://db:3307/inward?allowPublicKeyRetrieval=true&useSSL=false** but it is not working – Anshul Sharma May 20 '20 at 05:50
  • Using port `3306` is correct, you are using the docker compose network. It is exposed on the host on port `3307` but that's not relevant here. – wjans May 20 '20 at 06:46
  • 1
    @AnshulSharma: Are you sure the app is trying to connect to the host/port you are expecting it to? Can you validate it by increasing logging? – wjans May 20 '20 at 06:48
  • 1
    it may take some time to set up full things. So at first it may get "Connection refused", but you will get connection after several failed trying. – Mukit09 May 20 '20 at 07:04
  • @wjans, yes It is trying to connect to localhost:3307 but somehow my docker-machine has got IP address 192.168.99.100 and I am able to connect to it now through MySQL workbench. – Anshul Sharma May 20 '20 at 08:55
  • `localhost:3307` is definitely not correct, you should be connecting to `db:3306` from inside the docker container. Note that this is something completely different from what you are trying to do via your MySQL workbench. Then you are connecting from your docker host rather than from within another container. – wjans May 20 '20 at 13:11
  • Related, possibly duplicate: [Solving a “communications link failure” with JDBC and MySQL](https://stackoverflow.com/questions/6865538/solving-a-communications-link-failure-with-jdbc-and-mysql) – Mark Rotteveel May 21 '20 at 07:43
  • @MarkRotteveel I had a look at that one but that is not with docker, without docker yes that one would have helped. – Anshul Sharma May 21 '20 at 13:49
  • Well, the cause is the same. The _Caused by: java.net.ConnectException: Connection refused (Connection refused)_ indicates that from the perspective of your app, the specified host did not have its port open. – Mark Rotteveel May 21 '20 at 14:34
  • Yes you are right, the problem is the same but the setup is different, everything running on the local machine can be accessed through localhost:, but when docker involved there are containers for individual services and the communication between them is the concern, and I am trying to solve that here. – Anshul Sharma May 22 '20 at 02:14

1 Answers1

1

I could solve this problem with docker-compose file

services:
  db:
    image: mysql:5.7
    restart: always
    environment:
      - MYSQL_DATABASE=inward
      # So you don't have to use root, but you can if you like
      - MYSQL_USER=root
      # You can use whatever password you like
      - MYSQL_PASSWORD=unroot
      # Password for root access
      - MYSQL_ROOT_PASSWORD=unroot
    ports:
      # <Port exposed> : < MySQL Port running inside container>
      - 3307:3306

  app:
    build:
      context: ./
      dockerfile: Dockerfile
    depends_on:
      - db
    working_dir: /app
    command: [sh, -c, 'mkdir -p ~/logs/; cd /src ; mvn clean spring-boot:run -Dspring.profiles.active=local -DLOG_DIR=/root/logs/ -DLOG_FILE=hubstamper.log']
    ports:
      - 8080:8080
    volumes:
      - "${HOME}/.m2:/root/.m2"

and apllication-local.properties file

jdbcUrl=jdbc:mysql://db:3306/inward?allowPublicKeyRetrieval=true&useSSL=false
dataSource.user=root
dataSource.password=unroot
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048
driverClassName=com.mysql.jdbc.Driver
dataSource.driverClassName=com.mysql.jdbc.Driver

and docker file

FROM maven:3.5-jdk-8-alpine
COPY . /app

And please make sure every time you change anything in code, remove the old docker image, and create a new one(This is also I was missing in my approach).

Anshul Sharma
  • 1,018
  • 3
  • 17
  • 39