Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Gianluca-X/DigitalMoney/llms.txt

Use this file to discover all available pages before exploring further.

The docker-compose.yml at the root of the repository is the single source of truth for running the entire Digital Money House backend locally. It defines eight services — six Spring Boot microservices built from source, plus MySQL and RabbitMQ pulled from Docker Hub — and wires them together on a shared bridge network with explicit startup dependencies, resource limits, and a MySQL healthcheck that prevents application services from starting before the database is ready.

Services overview

The table below summarises every service defined in docker-compose.yml, including its image or build source, published port, dependencies, and memory limit.
ServiceImage / BuildHost Port → Container PortDepends OnMemory Limit
mysqlmysql:latest3308 → 3306512m
eureka-serverBuild (./eureka-server/Dockerfile)8761 → 8761512m
config-serverBuild (./config-server/Dockerfile)8888 → 8888eureka-server512m
auth-serviceBuild (./auth-service/Dockerfile)8082 → 8082mysql (healthy) + eureka-server1g
user-serviceBuild (./user-service/Dockerfile)8087 → 8087mysql (healthy) + eureka-server + config-server1g
accounts-serviceBuild (./accounts-service/Dockerfile)8084 → 8084mysql (healthy) + eureka-server + config-server1g
gatewayBuild (./gateway/Dockerfile)8085 → 8085eureka-server + config-server1g
rabbitmqrabbitmq:3-management5672 → 5672, 15672 → 15672512m
MySQL is mapped to host port 3308 (not the default 3306) to avoid collisions with a locally installed MySQL instance. Connect your database client to localhost:3308 when inspecting data directly.

Full docker-compose.yml

services:
  mysql:
    container_name: mysql
    mem_limit: 512m
    cpus: 0.5
    image: mysql:latest
    restart: unless-stopped
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${ACCOUNT_DB_DATABASE}
      MYSQL_USER: ${ACCOUNT_DB_USERNAME}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - "3308:3306"
    volumes:
      - mysql:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - back_network
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root --password=${MYSQL_ROOT_PASSWORD}"]
      interval: 30s
      retries: 5
      timeout: 10s

  eureka-server:
    container_name: eureka-server
    mem_limit: 512m
    cpus: 0.5
    build:
      context: .
      dockerfile: ./eureka-server/Dockerfile
    ports:
      - "8761:8761"
    networks:
      - back_network

  config-server:
    container_name: config-server
    mem_limit: 512m
    cpus: 0.5
    build:
      context: .
      dockerfile: ./config-server/Dockerfile
    ports:
      - "8888:8888"
    env_file:
      - .env
    environment:
      - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=${EUREKA_CLIENT_SERVICEURL_DEFAULTZONE}
    depends_on:
      - eureka-server
    networks:
      - back_network

  auth-service:
    container_name: auth-service
    mem_limit: 1g
    cpus: 1
    build:
      context: .
      dockerfile: ./auth-service/Dockerfile
    ports:
      - "8082:8082"
    env_file:
      - .env
    environment:
      - SPRING_DATASOURCE_URL=${AUTH_DB_URL}
      - SPRING_DATASOURCE_USERNAME=${AUTH_DB_USERNAME}
      - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
      - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
      - SPRING_JPA_DATABASE_PLATFORM=org.hibernate.dialect.MySQLDialect
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      mysql:
        condition: service_healthy
      eureka-server:
        condition: service_started
    networks:
      - back_network

  user-service:
    container_name: user-service
    mem_limit: 1g
    cpus: 1
    build:
      context: .
      dockerfile: ./user-service/Dockerfile
    ports:
      - "8087:8087"
    env_file:
      - .env
    environment:
      - SPRING_DATASOURCE_URL=${USER_DB_URL}
      - SPRING_DATASOURCE_USERNAME=${USER_DB_USERNAME}
      - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
      - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
      - SPRING_JPA_DATABASE_PLATFORM=org.hibernate.dialect.MySQLDialect
    depends_on:
      mysql:
        condition: service_healthy
      eureka-server:
        condition: service_started
      config-server:
        condition: service_started
    networks:
      - back_network

  accounts-service:
    container_name: accounts-service
    mem_limit: 1g
    cpus: 1
    build:
      context: .
      dockerfile: ./accounts-service/Dockerfile
    ports:
      - "8084:8084"
    env_file:
      - .env
    environment:
      - SPRING_DATASOURCE_URL=${ACCOUNT_DB_URL}
      - SPRING_DATASOURCE_USERNAME=${ACCOUNT_DB_USERNAME}
      - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
      - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
      - SPRING_JPA_DATABASE_PLATFORM=org.hibernate.dialect.MySQLDialect
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      mysql:
        condition: service_healthy
      eureka-server:
        condition: service_started
      config-server:
        condition: service_started
    networks:
      - back_network

  gateway:
    container_name: gateway
    mem_limit: 1g
    cpus: 1
    build:
      context: .
      dockerfile: ./gateway/Dockerfile
    ports:
      - "8085:8085"
    env_file:
      - .env
    environment:
      - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=${EUREKA_CLIENT_SERVICEURL_DEFAULTZONE}
    depends_on:
      - eureka-server
      - config-server
    networks:
      - back_network

  rabbitmq:
    container_name: rabbitmq
    mem_limit: 512m
    cpus: 0.5
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: guest
      RABBITMQ_DEFAULT_PASS: guest
    networks:
      - back_network

volumes:
  mysql:
  postgres_data:

networks:
  back_network:
    driver: bridge

MySQL healthcheck

MySQL is the only service configured with a Docker healthcheck. The check runs mysqladmin ping as the root user every 30 seconds with a 10-second timeout and up to 5 retries before the container is marked as unhealthy:
healthcheck:
  test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root --password=${MYSQL_ROOT_PASSWORD}"]
  interval: 30s
  retries: 5
  timeout: 10s
Services that declare condition: service_healthy for MySQL — auth-service, user-service, and accounts-service — will not start until this check passes. This prevents Communications link failure errors caused by a service attempting to open a connection pool before MySQL has finished initialising.

Database initialisation

On the very first run (when the mysql named volume does not yet exist), MySQL automatically executes init.sql from the docker-entrypoint-initdb.d/ directory. This script creates all three service databases and their dedicated users:
-- Create databases
CREATE DATABASE IF NOT EXISTS user_service_db;
CREATE DATABASE IF NOT EXISTS account_service_db;
CREATE DATABASE IF NOT EXISTS auth_service_db;

-- Create per-service users
CREATE USER IF NOT EXISTS 'user_service_user'@'%' IDENTIFIED BY 'nerea';
GRANT ALL PRIVILEGES ON user_service_db.* TO 'user_service_user'@'%';

CREATE USER IF NOT EXISTS 'account_service_user'@'%' IDENTIFIED BY 'nerea';
GRANT ALL PRIVILEGES ON account_service_db.* TO 'account_service_user'@'%';

CREATE USER IF NOT EXISTS 'auth_service_user'@'%' IDENTIFIED BY 'nerea';
GRANT ALL PRIVILEGES ON auth_service_db.* TO 'auth_service_user'@'%';

FLUSH PRIVILEGES;
init.sql only runs when MySQL initialises a fresh data directory. If the mysql volume already exists from a previous run, the script is skipped. To force re-initialisation, remove the volume with docker-compose down -v.

Networks

All eight services are connected to a single bridge network named back_network:
networks:
  back_network:
    driver: bridge
Docker’s embedded DNS resolves each service by its container name within this network, which is why database URLs and Eureka registration URLs use hostnames like mysql and eureka-server rather than IP addresses.

Volumes

Two named volumes are declared:
VolumeUsed byPurpose
mysqlmysql servicePersists database files across container restarts
postgres_dataReserved for the PostgreSQL migration branch; unused on main
The mysql volume is mounted at /var/lib/mysql inside the MySQL container, ensuring that all three service databases survive a docker-compose down (without -v).

Dockerfile pattern

Each microservice has its own Dockerfile located in its subdirectory. All Dockerfiles follow the same single-stage pattern: copy a pre-built JAR from target/ and launch it with the openjdk:21 base image.
FROM openjdk:21
ARG JAR_FILE=<service-name>/target/<service-name>.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
EXPOSE <port>
The build context for every service is the repository root (.), not the service subdirectory. This is required because the JAR_FILE ARG references a path like accounts-service/target/accounts-service.jar — a path that is only valid when the context includes the whole repository.
build:
  context: .
  dockerfile: ./accounts-service/Dockerfile
Because the build context is the entire repository, the first docker-compose up --build can be slow. Subsequent builds are fast thanks to Docker layer caching — only the layer that copies the JAR is invalidated when you rebuild a service.
The per-service Dockerfile locations and exposed ports are:
ServiceDockerfileExposed Port
eureka-server./eureka-server/Dockerfile8761
config-server./config-server/Dockerfile8888
auth-service./auth-service/Dockerfile8082
user-service./user-service/Dockerfile8087
accounts-service./accounts-service/Dockerfile8084
gateway./gateway/Dockerfile8085

Commands cheat sheet

GoalCommand
Start all services (foreground)docker-compose up
Start all services (detached)docker-compose up -d
Stop and remove containersdocker-compose down
Stop, remove containers and volumesdocker-compose down -v
Tail logs for one servicedocker-compose logs -f <service-name>
Rebuild images and restartdocker-compose up --build
Restart a single servicedocker-compose restart <service-name>
View running containersdocker-compose ps
Execute a command in a running containerdocker-compose exec <service-name> <cmd>
Running docker-compose down -v deletes the mysql named volume and all stored data. All three service databases will be recreated from init.sql on the next startup, but any application data will be permanently lost.

Build docs developers (and LLMs) love