
par Zelkulon19 mars 20251 min de lecture
Utiliser correctement Docker et Docker Compose pour les microservices : Builds multistages, découverte de services, health checks et un environnement de développement local complet.
Architecture Cible
┌─────────────────────────────────────────────────────────────┐ │ docker-compose.yml │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Next.js │ │ Order │ │ Payment │ │ │ │ :3000 │ │ Service │ │ Service │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ └───────────────┴───────────────┘ │ │ Bridge-Network │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │PostgreSQL│ │ RabbitMQ │ │ Redis │ │ │ │ :5432 │ │ :5672 │ │ :6379 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────────┘
Dockerfile Multistage (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 # Cache de couche pour les dépendances
COPY src src
RUN ./mvnw package -DskipTests -B
RUN java -Djarmode=layertools -jar target/*.jar extract --destination target/layers
# ─── Stage 2: Runtime (~150 Mo au lieu de ~600 Mo) ──────────────────
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" # Interface de gestion
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 # Démarrer uniquement quand la DB est prête !
rabbitmq:
condition: service_healthy
restart: unless-stopped
volumes:
postgres_data:Commandes Utiles
# Démarrer tous les services
docker compose up -d
# Infrastructure uniquement (pour le développement local)
docker compose up -d postgres rabbitmq redis
# Logs d'un service
docker compose logs -f order-service
# Reconstruire le service
docker compose up -d --build order-service
# État de tous les services
docker compose ps
# Ouvrir le shell du conteneur
docker compose exec order-service sh
# Tout arrêter + supprimer les volumes (réinitialiser la base de données)
docker compose down -vSéquence de Démarrage avec Health Checks
1. Démarrage de postgres, rabbitmq, redis
│
▼
2. Health checks (pg_isready, rabbit ping, redis ping)
│ tous sains
▼
3. Démarrage de order-service, payment-service
│
▼
4. Health checks (actuator/health)
│ tous sains
▼
5. Démarrage du frontend
Sans condition: service_healthy → Spring démarre avant que
PostgreSQL soit prêt → erreur de connexion !Conclusion
- Cohérence : "Ça marche sur ma machine" appartient au passé
- Isolation : Les services fonctionnent sans dépendances mutuelles
- Onboarding rapide : docker compose up – c'est prêt
- Parité production : L'environnement local correspond exactement au déploiement
- Scalabilité : docker compose up --scale order-service=3