Skip to main content

Docker Compose

Dockerfile

Spring Boot Services

It is the same Dockerfile for all 5 services.

Dockerfile
# ---------- Stage 1: Build ----------
FROM maven:3.9.11-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests

# ---------- Stage 2: Run ----------
FROM eclipse-temurin:21-jre-jammy
WORKDIR /app
COPY --from=builder /app/target/*.jar token-generator.jar
ENTRYPOINT ["java", "-jar", "token-generator.jar"]

React SPA

Dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:stable-alpine
# Build output goes into .../react-ui
COPY --from=build /app/build /usr/share/nginx/html/react-ui
COPY nginx.conf /etc/nginx/conf.d/default.conf

With the following nginx.conf

server {
listen 4001;
server_name _;

# Serve files from here
root /usr/share/nginx/html;

# Debug header to confirm we hit this server
add_header X-Spa-Debug "nginx-react-ui" always;

# Exact: /react-ui (no trailing slash)
# Serve index.html directly, no redirect, no internal rewrite
location = /react-ui {
try_files /react-ui/index.html =404;
}

# Prefix: /react-ui/ (assets + SPA routes)
# Try static files, then fall back to SPA index
location ^~ /react-ui/ {
try_files $uri $uri/ /react-ui/index.html;
}

# Safety: don’t emit absolute Location headers for any internal rewrites
absolute_redirect off;
}

Docker Compose Configuration

I managed to put together a Docker Compose configuration. The one important thing to remember: replace localhost with the container name for all inter-service communication.

The one exception

When your application needs to send the user’s browser to a new URL (like during an OAuth redirect), Docker container names won’t work. Browsers are outside Docker’s private network and can’t resolve container names. Here, you must use a valid host address such as:

  • http://localhost:7080/... (when testing locally), or
  • your actual server’s hostname/domain in production.

Rule of thumb

  • Service ↔ Service (inside Docker): use container names (e.g., mysql, registration, bff).
  • Browser ↔ App (outside Docker): use hostnames (localhost, or your domain).

Following this simple rule ensures your services talk to the right neighbors and your users can still access your app correctly.

As an example the bff/REACT_URI: http://localhost:7080/react-ui keeps localhost since it is a redirection url.

docker-compose.yml

gist link of of the file: https://gist.github.com/Mehdi-HAFID/97ce26dde39ef0a4e662e5235a2ec951

docker-compose.yml
services:
mysql:
image: mysql:9.4
container_name: mysql
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'CcmN*`6@3T9H%P#yg^V<7v'
MYSQL_DATABASE: identity_hub
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: [ "CMD-SHELL", "mysqladmin ping -h localhost -uroot -p\"$MYSQL_ROOT_PASSWORD\" || exit 1" ]
interval: 5s
timeout: 2s
retries: 5
networks:
- nidam-net

registration:
build:
context: ./registration
dockerfile: Dockerfile
container_name: registration
ports:
- "4000:4000"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/identity_hub?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: 'CcmN*`6@3T9H%P#yg^V<7v'
SERVER_PORT: 4000
depends_on:
mysql:
condition: service_healthy
networks:
- nidam-net

token-generator:
build:
context: ./token-generator
dockerfile: Dockerfile
container_name: token-generator
ports:
- "4002:4002"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/identity_hub?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: 'CcmN*`6@3T9H%P#yg^V<7v'
SERVER_PORT: 4002
REVERSE_PROXY_URI: http://reverse-proxy:7080
ISSUER: http://reverse-proxy:7080/auth
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:4002/auth/.well-known/openid-configuration" ]
interval: 5s
timeout: 2s
retries: 12
depends_on:
mysql:
condition: service_healthy
networks:
- nidam-net

reverse-proxy:
build:
context: ./reverse-proxy
dockerfile: Dockerfile
container_name: reverse-proxy
ports:
- "7080:7080"
environment:
SERVER_PORT: 7080
REACT_URI: http://nidam-spa:4001/react-ui
AUTHORIZATION_SERVER_URI: http://token-generator:4002/auth
BFF_URI: http://bff:7081
healthcheck:
# test: [ "CMD", "curl", "-f", "http://localhost:7080/actuator/health/readiness" ]
test: [ "CMD", "curl", "-f", "http://localhost:7080/auth/.well-known/openid-configuration" ]
interval: 5s
timeout: 2s
retries: 12
depends_on:
token-generator:
condition: service_healthy
networks:
- nidam-net

nidam:
build:
context: ./nidam
dockerfile: Dockerfile
container_name: nidam
ports:
- "4003:4003"
environment:
SERVER_PORT: 4003
SLEEP_SECONDS: "10"
ISSUER: http://reverse-proxy:7080/auth
REVERSE_PROXY_URI: http://reverse-proxy:7080
depends_on:
reverse-proxy:
condition: service_healthy
networks:
- nidam-net

bff:
build:
context: ./bff
dockerfile: Dockerfile
container_name: bff
ports:
- "7081:7081"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/identity_hub?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: 'CcmN*`6@3T9H%P#yg^V<7v'
SERVER_PORT: 7081
# REVERSE_PROXY_URI: http://reverse-proxy:7080
ISSUER: http://reverse-proxy:7080/auth
REACT_URI: http://localhost:7080/react-ui
RESOURCE_SERVER_URI: http://nidam:4003
depends_on:
reverse-proxy:
condition: service_healthy
networks:
- nidam-net

spa:
build:
context: ./nidam-spa
dockerfile: Dockerfile
container_name: nidam-spa
# ports:
# - "4001:4001"
environment:
REACT_APP_BACKEND_REGISTRATION_URL: http://registration:4000/
REACT_APP_REVERSE_PROXY_URI: http://reverse-proxy:7080
REACT_APP_BASE_URI: http://reverse-proxy:7080/react-ui
REACT_APP_RESOURCE_SERVER_URI: http://reverse-proxy:7080/bff/api
REACT_APP_LOGIN_URL: http://reverse-proxy:7080/bff/oauth2/authorization/token-generator
depends_on:
- bff
networks:
- nidam-net

volumes:
mysql_data:
networks:
nidam-net:
driver: bridge

Build & Run

Project Structure

  • Create a root directory (e.g., Nidam).
  • Place all 6 repositories inside this directory.
  • Copy the docker-compose.yml file into the root directory.

Nidam root folder

Build & Start

From the terminal, navigate to the root directory and run:

docker compose up --build -d

Once the services are running, open your browser and go to http://localhost:7080/react-ui to access Nidam.