Search code examples
mysqlspring-bootdockerdocker-composedeployment

Why does my docker-compose app fail on first run and work on the second try?


I have want to dockerize a spring boot application with mysql database using docker compose and it fails on first run and works on second and i would like to find an explainnation. I suppose on the first run, it creates the database or something and the spring boot app fails because something is not initialized properly but i am not sure. How can i solve this?

version: '5'
services:
  mysql:
    image: mysql:latest
    ports:
      - "3307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: rentalapp
    command: mysqld --sql_mode=""
    volumes:
      - ./my.cnf:/etc/mysql/my.cnf
    container_name: mysqlimage1

  app:
    image: crudimage:crudapp
    ports:
      - "8090:8080"
    environment:
      SPRING_JPA_GENERATE_DDL: true
      SPRING_JPA_HIBERNATE_DDL_AUTO: update
      SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.MySQLDialect
      SPRING_JPA_SHOW_SQL: true
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/rentalapp
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root
      SERVER_ERROR_INCLUDE_MESSAGE: always
    depends_on:
      - mysql
    container_name: crudappimage1
FROM openjdk:17

COPY target/crudapp.jar .

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "crudapp.jar"]
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform= org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
spring.datasource.url= jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB_NAME:rentalapp}
spring.datasource.username= ${MYSQL_USER:root}
spring.datasource.password= ${MYSQL_PASSWORD:root}

server.error.include-message=always

Solution

  • Based on docker compose file i can guess/say that the problem is very popular one: In your config docker compose run mysql first and after it the application. Here application start faster than mysql will be ready to have connections.

    To fix it add one more param on application part in docker compose file:

    app:
        image: crudimage:crudapp
        ports:
          - "8090:8080"
        environment:
          SPRING_JPA_GENERATE_DDL: true
          SPRING_JPA_HIBERNATE_DDL_AUTO: update
          SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.MySQLDialect
          SPRING_JPA_SHOW_SQL: true
          SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/rentalapp
          SPRING_DATASOURCE_USERNAME: root
          SPRING_DATASOURCE_PASSWORD: root
          SERVER_ERROR_INCLUDE_MESSAGE: always
        depends_on:
          - mysql
             condition: service_completed_successfully
        container_name: crudappimage1 
    

    What does it mean ? service_completed_successfully - specifies that a dependency is expected to run to successful completion before starting a dependent service.