6

I've been trying to set up a connection between a backend (runs on Spring Boot) container and a pre-built MySQL container. However, I cannot get it to connect. My docker compose file is:

version: '3.7'

services:

  test-mysql:
    image: mysql
    restart: always
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_DATABASE: testdb
      MYSQL_USER: test
      MYSQL_PASSWORD: test
      MYSQL_ROOT_PASSWORD: root

  backend:
    depends_on: 
      - test-mysql
    build: 
      context: backend
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    restart: always  

volumes:
  db_data: {}

my application.properties:

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url=jdbc:mysql://test-mysql:3306/testdb?autoReconnect=true&failOverReadOnly=false&maxReconnects=10
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=test
spring.datasource.password=test

When I use docker-compose up, Spring Boot is not able to recognize the container name test-mysql. It throws: java.net.UnknownHostException

When I change it to an IP, it says connection refused. I have been looking everywhere and couldn't come with a fix. I hope anyone can help me out. Thank you!

4 Answers 4

2

You have to mention the backend mysql properties in the composer file like below,

backend:
depends_on: 
  - test-mysql
build: 
  context: backend
  dockerfile: Dockerfile
ports:
  - "8080:8080"
restart: always
environment:
        SPRING_DATASOURCE_URL: jdbc:mysql://test- 
           mysql:3306/testdbautoReconnect=true&failOverReadOnly=false&maxReconnects=10
        SPRING_DATASOURCE_USERNAME: test
        SPRING_DATASOURCE_PASSWORD: test
links:
  - test-mysql:test-mysql

If this wouldn't work try to create a common docker network and add it to your composer file like below,

backend:
depends_on: 
  - test-mysql
build: 
  context: backend
  dockerfile: Dockerfile
ports:
  - "8080:8080"
restart: always
environment:
        SPRING_DATASOURCE_URL: jdbc:mysql://test- 
           mysql:3306/testdbautoReconnect=true&failOverReadOnly=false&maxReconnects=10
        SPRING_DATASOURCE_USERNAME: test
        SPRING_DATASOURCE_PASSWORD: test
networks:
      -common-network

test-mysql:
image: mysql
restart: always
volumes:
  - db_data:/var/lib/mysql
environment:
  MYSQL_DATABASE: testdb
  MYSQL_USER: test
  MYSQL_PASSWORD: test
  MYSQL_ROOT_PASSWORD: root
networks:
      -common-network

#Docker Networks
networks:
    common-network:
        driver: bridge

#Volumes
volumes:
    dbdata:
        driver: local
Sign up to request clarification or add additional context in comments.

8 Comments

Hello thanks for your response. I still get java.net.UnknownHostException
Also, it seems like the env variables are not overriding the application.properties variables. Any idea about this?
Try to expose mysql port also. test-mysql: image: mysql restart: always ports: - "3306:3306" volumes: - db_data:/var/lib/mysql environment: MYSQL_DATABASE: testdb MYSQL_USER: test MYSQL_PASSWORD: test MYSQL_ROOT_PASSWORD: root
@Steven if this is not working, you should try setting a network like my second example. Probably that would be the issue. Containers can't identify their hosts. Containers can communicate easily with common docker network.
@Steven try with adding a link before trying the second example. Updated my answer also. links: - test-mysql:test-mysql
|
1

I hope this has been already solved but in case it hasn't yet, the problem lies in mysql docker container lagging behind the start up.

Another problem is that you might need to build the jar file and then copy it the container. That's a big problem because when you build the jar file, the database with db as hostname is unavailable. So when you are building the jar file, skip the test. This is bash script i created but you can run command one by one:

#!/bin/bash 
cd storage-service
rm -rf target/
mvn clean compile package -Dmaven.test.skip=true
cd ..

docker-compose up

In case you want to initialize db in the container. That file is in the folder env where i have a file database.env

-- create the databases
CREATE DATABASE IF NOT EXISTS model_storage;
-- create the users for each database
CREATE USER 'arsene'@'localhost' IDENTIFIED BY 'arsene';
GRANT CREATE, ALTER, INDEX, LOCK TABLES, REFERENCES, UPDATE, DELETE, DROP, SELECT, INSERT ON `model_storage`.* TO 'arsene'@'localhost';

FLUSH PRIVILEGES;

The backend service Dockerfile looks like this:

FROM adoptopenjdk/openjdk11
COPY target/*.jar storage.jar
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /storage.jar" ]
EXPOSE 8089

The database env file looks like this:

MYSQL_ROOT_PASSWORD=arsene
MYSQL_DATABASE=model_storage
MYSQL_USER=arsene
MYSQL_PASSWORD=arsene

DATABASE_HOST=model_storage
DATABASE_USER=arsene
DATABASE_PASSWORD=arsene
DATABASE_NAME=model_storage
DATABASE_PORT=3306

In case you intend to pass JAVA_OPTS env in the image. These can be used later as seen in docker-compose.yml below

Your backend (the service that depends on the mysql db) needs to restart until the docker-compose is able to resolve the the container name of mysql, in my case its name is db. And don't forget to include datasource connection properties in docker-compose backend service image as i did below. I am not an expert in spring boot and neither in docker but for now it works!

Below is the way mine is structured:
I am using docker version: "3.8"

Storage service
storage-service:
    container_name: storage-service
    restart: always
    build:
        context: storage-service
    image: "service_storage_image"
    depends_on:
        - db
    ports:
        - "8089:8089"
    links:
        - db  
    env_file:
        - env/database.env
    environment:
        WAIT_HOSTS: db:3306
        SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/model_storage?allowPublicKeyRetrieval=true&useSSL=false
        SPRING_DATASOURCE_USERNAME: root
        SPRING_DATASOURCE_PASSWORD: arsene
    healthcheck:
        test: "/usr/bin/mysql --user=arsene --password=arsene--execute \"SHOW DATABASES;\""
        interval: 2s
        timeout: 20s
        retries: 10
    environment:
        - JAVA_OPTS=
        -DEUREKA_SERVER=http://eureka-registry-server:7070/eureka
        -DZIPKIN_SERVER=http://zipkin:9411/
    networks:
        - private-network-mms

My db in docker-compose is structured this way:

Mysql database
db:
    hostname: db
    container_name: db
    image: "mysql:latest"
    env_file:
        - env/database.env
    volumes:
        - type: bind
            source: ./env/setup.sql
            target: /docker-entrypoint-initdb.d/setup.sql
        - db_volume:/var/lib/mysql
    ports:
       - 3307:3306
    networks:
        - private-network-mms

Comments

0

You can define a common network on which both the application server and the database can connect. Please check the file (docker-compose.yml) below where I have defined a common network: backend

# Docker Compose file Reference (https://docs.docker.com/compose/compose-file/)

version: '3.7'

# Define services
services:
  # App backend service
  app-server:
    # Configuration for building the docker image for the backend service
    build:
      context: . # Use an image built from the specified dockerfile in the `springboot-app-server` directory.
      dockerfile: Dockerfile
    ports:
      - "8080:8080" # Forward the exposed port 4000 on the container to port 4000 on the host machine
    restart: always
    depends_on: 
      - db # This service depends on mysql. Start that first.
    environment: # Pass environment variables to the service
      SPRING_DATASOURCE_URL: jdbc:mysql://test-mysql:3306/testdb?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false
      SPRING_DATASOURCE_USERNAME: test
      SPRING_DATASOURCE_PASSWORD: test
    networks: # Networks to join (Services on the same network can communicate with each other using their name)
      - backend

  # Database Service (Mysql)
  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    restart: always
    environment:
      MYSQL_DATABASE: testdb
      MYSQL_USER: test
      MYSQL_PASSWORD: test
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - backend  

# Volumes
volumes:
  db-data:

# Networks to be created to facilitate communication between containers
networks:
  backend: 

I have written a blog and a simple working Spring Boot MySQL application on GitHub which tells about using Docker Compose. Please check: http://softwaredevelopercentral.blogspot.com/2020/10/spring-boot-mysql-docker-compose-example.html

Comments

0

If you would like to use this test-mysql in your spring config

spring.datasource.url=jdbc:mysql://test-mysql:3306/testdb?autoReconnect=true&failOverReadOnly=false&maxReconnects=10

Then add the hostname attribute at service test-mysql

version: '3.7'

services:

  test-mysql:
    image: mysql
    hostname: test-mysql
    ...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.