3

I'm getting this exception while trying to run docker compose

app-server_1  | com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
app-server_1  | 
app-server_1  | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

My docker-compose.yml looks like this

version: "3.7"

services:
  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    restart: always
    environment:
      MYSQL_DATABASE: ppmt
      MYSQL_USER: vilius
      MYSQL_PASSWORD: vilius123
      MYSQL_ROOT_PASSWORD: root
    networks:
      - backend

  app-server:
    build:
      context: simple-fullstack
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    restart: always
    depends_on:
      - db
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/ppmt?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
      SPRING_DATASOURCE_USERNAME: vilius
      SPRING_DATASOURCE_PASSWORD: vilius123
    networks:
      - backend

networks:
  backend:

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url =jdbc:mysql://db:3306/ppmt?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
spring.datasource.username=vilius
spring.datasource.password=vilius123

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.initialize=true

Have been struggling for a while and seen people with similar problems, but still didn't found the solution. Is there a problem with my docker-compose.yml?

2
  • Check whether IP address or hostname in JDBC URL is correct or not Commented Nov 21, 2020 at 2:12
  • My suggestion will be to wrap jdbc:mysql... string in double quotes, because of : character in yaml Commented Nov 21, 2020 at 3:58

2 Answers 2

1

The problem here is, your application is trying to connect to mysql before it's ready. Accordinfg to official documentation

You can control the order of service startup and shutdown with the depends_on option. Compose always starts and stops containers in dependency order, where dependencies are determined by depends_on, links, volumes_from, and network_mode: "service:...".

However, for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it’s running. There’s a good reason for this.

The problem of waiting for a database (for example) to be ready is really just a subset of a much larger problem of distributed systems. In production, your database could become unavailable or move hosts at any time. Your application needs to be resilient to these types of failures.

To handle this, design your application to attempt to re-establish a connection to the database after a failure. If the application retries the connection, it can eventually connect to the database.

Use a tool such as wait-for-it, dockerize, sh-compatible wait-for, or RelayAndContainers template. These are small wrapper scripts which you can include in your application’s image to poll a given host and port until it’s accepting TCP connections.

From here.

I found that, spring boot 2.3.4 does not stop your app if db connection fails. It will retry if the app tries to access db and connection will be established if db is up.

Another workaround is, start your db first and then start your app.

docker-compose up db
docker-compose up app-server
Sign up to request clarification or add additional context in comments.

4 Comments

I find it weird that this answer is accepted because depends_on: db is already specified in the app-server definition.
depends_on just makes sure that the db is running before app-server, it does not mean that db will ready to accept request before your app-server starts.
Gotcha. A better solution might then be to use wait-for script (github.com/Eficode/wait-for). Otherwise, using docker-compose doesn't really make sense in my opinion.
Yes, it is also mentioned in the answer as docker docs recommended it. I also added my findings as another option.
1

Adding to @Shawrup's excellent description of what's happening, another solution is to add a healtcheck to the MySQL container. This will cause Docker Compose to wait for the healthcheck to be successful before starting any dependent containers.

Your MySQL container configuration could look something like this:

  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    restart: always
    environment:
      MYSQL_DATABASE: ppmt
      MYSQL_USER: vilius
      MYSQL_PASSWORD: vilius123
      MYSQL_ROOT_PASSWORD: root
    networks:
      - backend
    healthcheck:
      test: "/usr/bin/mysql --user=root --password=root --execute \"SHOW DATABASES;\""
      interval: 2s
      timeout: 20s
      retries: 10

1 Comment

I also changed on spring container to restart it if it fails, because depends_on only assures that db will start, but most of the time db doesn't load that fast as spring project and it causes link_failure.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.