2

I have two Spring apps that shares the same Mysql database. They work perfectly when I run them without docker-compose. My host machine is Windows 10 professional.

application.properties

server.port=8085
spring.jpa.show-sql=true
spring.jackson.serialization.write-dates-as-timestamps=false
spring.jpa.hibernate.ddl-auto=update
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306 /webDatabase?autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=my-secret-pw

Dockerfile

FROM openjdk:8-jdk-alpine
ADD target/web-spring-boot.jar web-spring-boot.jar
EXPOSE 8085
ENTRYPOINT ["java","-jar", "web-spring-boot.jar"]

I created this docker-compose.yml based on other examples.

version: '3'
services:
  web:
    build: ./web
    ports:
    - "8085:8085"
    depends_on:
    - "database"
  solver:
    build: ./solver
    ports:
    - "8095:8095"
    depends_on:
    - "database"
  database:
    image: "mysql:latest"
    ports:
    - "3306:3306"
    environment:
    - MYSQL_ROOT_PASSWORD=my-secret-pw
    - MYSQL_DATABASE=webDatabase
    healthcheck:
            test: "/usr/bin/mysql --user=root --password=my-secret-pw --execute \"SHOW DATABASES;\""
            interval: 10s
            timeout: 20s
            retries: 10
volumes:
  logvolume01: {}

It doesn´t work. After startup only the Mysql container is running.

Here is part of the output with Spring logs

solver_1 | 2019-01-04 22:55:15.698 WARN 1 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08S01 solver_1 | 2019-01-04 22:55:15.698 ERROR 1 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Communications link failure solver_1 | solver_1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

What am I missing in the configuration? Does application.properties are ignored when running with composing?

Thadeu Melo
  • 947
  • 14
  • 40
  • Two questions, are you certain the web Dockerfile is in fact under ./web? And what commands are you using to run with docker and docker-compose? – maininformer Jan 04 '19 at 16:17
  • @plumSemPy yes, I can see both spring start-ups. I´m add parts of the log. To run them it is only `docker run`after `docker build` – Thadeu Melo Jan 04 '19 at 16:31
  • Please refer to [https://stackoverflow.com/questions/26548505/org-hibernate-hibernateexception-access-to-dialectresolutioninfo-cannot-be-null][1] – Ritabrata Jan 04 '19 at 16:46
  • @Ritabrata I don´t see the relation. – Thadeu Melo Jan 04 '19 at 19:02

3 Answers3

2

The Spring-Boot applications try to connect to localhost:3306. This works fine as long as they do not run within a container.

When running within the container the connection is also tried to establish against localhost (but this time within the spring-boot docker container). This fails, obviously, as within your spring-boot container there is no mysql running.

The mysql service is accessible within the docker network by it's alias name (database).

Reconfigure your spring.datasource.url to

spring.datasource.url=jdbc:mysql://database:3306/webDatabase?autoReconnect=true&useSSL=false

This can be either done within your application.properties or by using environment variables within your docker-compose file.

user1595178
  • 161
  • 1
  • 6
  • It seems to have improved. However, I´m now getting this error "web_1 | 2019-01-04 21:57:09.037 WARN 1 --- [nio-8085-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1046, SQLState: 3D000 web_1 | 2019-01-04 21:57:09.037 ERROR 1 --- [nio-8085-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : No database selected" – Thadeu Melo Jan 04 '19 at 21:58
  • Did you add the part /webDatabase?autoReconnect=true&useSSL=false ? I missed it due to the space – user1595178 Jan 04 '19 at 22:37
  • I'm trying to follow this guys examples: https://springbootdev.com/2018/01/08/docker-spring-boot-and-spring-data-jpa-mysql-rest-api-example-with-docker-with-docker-compose/ – Thadeu Melo Jan 04 '19 at 22:56
2

Instead of hardcoding the MySQL datasource string in your application.properties, you can pass it from the docker-compose configuration. Moreover, you are using service name 'database' defined in docker-compose to create a hardcoded entry in your application.properties.

Do avoid that do something like below:

   version: '3'
    services:
      web:
        build: ./web-spring
        ports:
        - "8085:8085"
        depends_on:
        - "database"
    environment:
    - SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/mysqldatabase?useSSL=false&allowPublicKeyRetrieval=true
    volumes:
    - /data/spring-boot-app
  solver:
    build: ./solver
    ports:
    - "8095:8095"
    depends_on:
    - "database"
    - "web"
    environment:
    - SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/mysqldatabase?useSSL=false&allowPublicKeyRetrieval=true
  database: 
    image: "mysql:latest"
    ports:
    - "3306:3306"
    environment:
    - MYSQL_ROOT_PASSWORD=my-secret-pw
    - MYSQL_DATABASE=mysqldatabase
    volumes:
      - /data/mysql
    healthcheck:
      test: ["CMD", "mysqldatabase" ,"ping", "-h", "database"]
      timeout: 1s
      retries: 100
volumes:
  logvolume01: {}

Note: You can convert any Spring Boot Common Application Properties into a environment variable by replacing dot(.) with underscore(_)

1

I was finnaly able to run the app.

Here are the configurations

server.port=8095
spring.jpa.show-sql=true
spring.jackson.serialization.write-dates-as-timestamps=false
#spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.datasource.url=jdbc:mysql://database:3306/mysqldatabase?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=my-secret-pw

docker-compose.yml

version: '3'
services:
  web:
    build: ./web-spring
    ports:
    - "8085:8085"
    depends_on:
    - "database"
    volumes:
    - /data/spring-boot-app
  solver:
    build: ./solver
    ports:
    - "8095:8095"
    depends_on:
    - "database"
    - "web"    
  database: 
    image: "mysql:latest"
    ports:
    - "3306:3306"
    environment:
    - MYSQL_ROOT_PASSWORD=my-secret-pw
    - MYSQL_DATABASE=mysqldatabase
    volumes:
      - /data/mysql
    healthcheck:
      test: ["CMD", "mysqldatabase" ,"ping", "-h", "database"]
      timeout: 1s
      retries: 100
volumes:
  logvolume01: {}
Thadeu Melo
  • 947
  • 14
  • 40