Search code examples
javaspring-bootdockermavendocker-compose

What would be the issue if I received "Socket fail to connect to host" docker-compose


I'm trying to connect to my container with my empty java maven project. But I received an error Socket fail to connect to host:address=(host=studentdb)(port=3306)(type=primary). studentdb

What would be the problem in my docker-compose.yml

version: '3.8'

services:
  mariadb:
    build:
      context: .
    container_name: studentdb
    networks:
      - default
    ports:
      - "3306:3306"
    expose:
      - "3306"
    volumes:
      - ./data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_APPLICATION_USER}
      MYSQL_PASSWORD: ${DB_APPLICATION_PASSWORD}

And this is my application.properties:

spring.application.name=student
spring.datasource.url=jdbc:mariadb://studentdb:3306/student
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.properties.javax.persistence.validation.mode=none
server.error.whitelabel.enabled=false

Solution

  • How you connect to the database will depend on whether you are connecting from the host or from another container.

    version: '3.8'
    
    services:
      mariadb:
        image: mariadb:latest
        container_name: studentdb
        ports:
          - "3306:3306"
        environment:
          MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
          MYSQL_DATABASE: ${DB_NAME}
          MYSQL_USER: ${DB_APPLICATION_USER}
          MYSQL_PASSWORD: ${DB_APPLICATION_PASSWORD}
    

    I'm assuming that you have an .env file set up with the variables referenced in your docker-compose.yml.

    DB_ROOT_PASSWORD=secret
    DB_NAME=test
    DB_APPLICATION_USER=user
    DB_APPLICATION_PASSWORD=password
    

    From Host

    Since you are exposing port 3306 on the mariadb service you can connect to this directly from the host using 127.0.0.1 as the database IP.

    MYSQL_PWD=password mysql -h 127.0.0.1 -u user
    

    Note: I'm using the username and password from .env.

    From Another Container

    If you are connecting to the database from another container (on the same Docker network) then you'd use either the service name (mariadb) or the container name (studentdb) rather than an IP address.

    For example, adding another service to the Docker Compose stack above.

      client:
        image: mariadb:latest
        command: "bash -c 'sleep 5; MYSQL_PWD=${DB_APPLICATION_PASSWORD} mariadb -h mariadb -u ${DB_APPLICATION_USER}'"
    

    The command waits 5 seconds (crude way to ensure that the database is ready) and then connects using the credentials defined in .env and mariadb as the database host name.

    🚨 If you want to use the service or container name to reference the database host then you should do so from another container in the same Docker network.