Docker Microservices Setup: From Zero to Running Environment

Docker Microservices Setup: From Zero to Running Environment
by Zelkulon19 March 20251 min read

Using Docker and Docker Compose correctly for microservices: Multistage Builds, Service Discovery, Health Checks and a complete local development environment.

Target Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   docker-compose.yml                        β”‚
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚  β”‚  Next.js β”‚    β”‚  Order   β”‚    β”‚  Payment β”‚              β”‚
β”‚  β”‚  :3000   β”‚    β”‚  Service β”‚    β”‚  Service β”‚              β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜              β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚                    Bridge-Network                           β”‚
β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚       β”‚PostgreSQLβ”‚   β”‚ RabbitMQ β”‚   β”‚  Redis   β”‚           β”‚
β”‚       β”‚  :5432   β”‚   β”‚  :5672   β”‚   β”‚  :6379   β”‚           β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Multistage Dockerfile (Spring Boot)

# ─── Stage 1: Build ────────────────────────────────────────────
FROM eclipse-temurin:21-jdk-alpine AS build
WORKDIR /app

COPY pom.xml .
COPY .mvn .mvn
COPY mvnw .
RUN ./mvnw dependency:go-offline -B  # Layer cache for dependencies

COPY src src
RUN ./mvnw package -DskipTests -B
RUN java -Djarmode=layertools -jar target/*.jar extract     --destination target/layers

# ─── Stage 2: Runtime (~150 MB instead of ~600 MB) ──────────────────
FROM eclipse-temurin:21-jre-alpine AS runtime
WORKDIR /app

COPY --from=build /app/target/layers/dependencies/          ./
COPY --from=build /app/target/layers/spring-boot-loader/    ./
COPY --from=build /app/target/layers/application/           ./

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

EXPOSE 8081
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s     CMD wget -qO- http://localhost:8081/actuator/health || exit 1

ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

Docker Compose

services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: ${DB_PASS:-secret}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      retries: 5

  rabbitmq:
    image: rabbitmq:3.13-management-alpine
    ports:
      - "5672:5672"
      - "15672:15672"  # Management UI
    healthcheck:
      test: ["CMD", "rabbitmq-diagnostics", "ping"]
      interval: 30s

  order-service:
    build: ./order-service
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/orderdb
      SPRING_RABBITMQ_HOST:  rabbitmq
    ports:
      - "8081:8081"
    depends_on:
      postgres:
        condition: service_healthy   # Only start when DB is ready!
      rabbitmq:
        condition: service_healthy
    restart: unless-stopped

volumes:
  postgres_data:

Useful Commands

# Start all services
docker compose up -d

# Infrastructure only (for local development)
docker compose up -d postgres rabbitmq redis

# Logs of a service
docker compose logs -f order-service

# Rebuild service
docker compose up -d --build order-service

# Status of all services
docker compose ps

# Open container shell
docker compose exec order-service sh

# Stop everything + delete volumes (reset database data)
docker compose down -v

Startup Sequence with Health Checks

1. Start postgres, rabbitmq, redis
        β”‚
        β–Ό
2. Health checks (pg_isready, rabbit ping, redis ping)
        β”‚ all healthy
        β–Ό
3. Start order-service, payment-service
        β”‚
        β–Ό
4. Health checks (actuator/health)
        β”‚ all healthy
        β–Ό
5. Frontend starts

Without condition: service_healthy β†’ Spring starts before
PostgreSQL is ready β†’ connection error!

Summary

  • Consistency: "Works on my machine" is a thing of the past
  • Isolation: Services run without mutual dependencies
  • Fast onboarding: docker compose up – done
  • Production parity: Local environment matches deployment exactly
  • Scalability: docker compose up --scale order-service=3
Docker Microservices Setup: From Zero to Running Environment