0

I have a spring-boot 2.16 service that connects to a my-sql data base. It works as expected as far as all the components are on the same host. I tried to improve the solution and to have a docker container running the sprin-boot service with Tomcat embedded and another docker container running the my-sql server. The same code doesn't work any more. here is the exception:

 2019-06-28 12:23:48 ERROR com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Exception during pool initialization.
 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 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.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at  sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:988)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:341)
....
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:211)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:300)
... 66 common frames omitted

So, it's like the my-sql server IP address is not found or the server is not running, etc. Here is the docker-compse.yml file:

version: "2"
services:
  rdf-data:
    container_name: rdf-data
    image: mysql:latest
    environment:
      MYSQL_DATABASE: test
      MYSQL_USER: nicolas
      MYSQL_PASSWORD: mysql
      MYSQL_ROOT_PASSWORD: mysql
    ports:
      - 3306:3306
      - 33060:33060
    hostname: rdf-data
    networks:
      net1:
        ipv4_address: 192.19.0.4
  rdf-core:
    image: openjdk:8-jdk-alpine
    depends_on:
      - rdf-data
    container_name: rdf-core
    links:
      - rdf-data:rdf-data
    volumes:
      - ../docker:/usr/local/share/rdf
    ports:
      - "8080:8080"
    entrypoint: /usr/local/share/rdf/run.sh
    hostname: rdf-core
    environment:
      PROFILE: "default"
      SERVER_PORT: "8080"
  networks:
    net1:
      ipv4_address: 192.19.0.8
networks:
  net1:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
  ipam:
    driver: default
    config:
      - subnet: 192.19.0.0/24
        gateway: 192.19.0.1

Here there are two containers: rfd-core having the IP address of 192.19.0.8 and rdf-data having the IP address 192.19.0.4. Each container is able to ping the other. The hst machine is able to ping each container. From the host machine I'm able to correctly connect to the my-sql server running on rfd-data using the my-sql command line client. However, my service connection shown here below doesn't work:

database=mysql
spring.datasource.url=jdbc:mysql://192.19.0.4/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=mysql
spring.datasource.driver-class=com.mysql.cj.jdbc.MysqlXADataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.idleTimeout=600000
spring.datasource.hikari.maxLifetime=1800000
...

Is there anything I'm missing?

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • `mysqld --verbose --help | grep bind-address` check the bind-address – Ntwobike Jun 28 '19 at 13:07
  • As your services share the same network why don't use service discovery feature provided by docker. So instead of setting manually ip address, you can use service name. – akuma8 Jun 28 '19 at 13:28
  • @akuma8 : unrelated but thanks anyway for your time. –  Jun 28 '19 at 14:31
  • @Ntwobike: have checked before posting. –  Jun 28 '19 at 14:32

1 Answers1

2

Try specifying the parameters of the spring boot app in the environment part of your docker-compose file :

 rdf-core:
    image: openjdk:8-jdk-alpine
    depends_on:
      - rdf-data
    container_name: rdf-core
        links:
          - rdf-data:rdf-data
        volumes:
          - ../docker:/usr/local/share/rdf
        ports:
          - "8080:8080"
        entrypoint: /usr/local/share/rdf/run.sh
        hostname: rdf-core
        environment:
          PROFILE: "default"
          SERVER_PORT: "8080"
          spring.datasource.url=jdbc:mysql://ipaddress/test?useSSL=false
          spring.datasource.username=root
          spring.datasource.password=mysql
          spring.datasource.driver-class=com.mysql.cj.jdbc.MysqlXADataSource
          spring.datasource.driver-class-name=com.mysql.jdbc.Driver
          spring.datasource.hikari.connectionTimeout=30000
          spring.datasource.hikari.idleTimeout=600000
          spring.datasource.hikari.maxLifetime=1800000

Another possible cause of the problem : the depends_on doesn't guarantee that the dependency container is fully running. so if the MySQL containers takes more time to fully start than the Spring Boot container, the connection fails.

Take a look at this:

Spring Boot + docker-compose + MySQL: Connection refused

There are few possible ways to make a container wait for another: Use the restart on failure feature, or docker compose wait ( Github link )

med.b
  • 465
  • 2
  • 12
  • 21
  • interesting. Any particular reason you think that it would work better if parameters are passed in a different way ? But I'll try I prommiss. –  Jun 28 '19 at 14:36
  • 1
    I had a similar issue when starting different containers using `docker-compose`. When trying to identify the problem, I found out that when launching everything with `docker compose`, and launching the Spring Boot app with `mvn spring-boot:run` , it works fine, so there's probably a problem with reading/finding spring boot configuration inside the container, and passing them in the environment section of the docker-compose file solved the issue. this may help https://stackoverflow.com/questions/46057625/externalising-spring-boot-properties-when-deploying-to-docker/46058452 – med.b Jun 28 '19 at 15:20
  • I'm updating the case with the results of the last tests. My issue was produced by the fact of using the MySQL JDBC driver which comes with Spring Boot 2.1.6.RELEASE and the mysql:latest image. They are not compatible. Using mysql:5.7 image instead solves the issue. Many thanks to all for your help and support. –  Jun 29 '19 at 15:16