Aller au contenu principal

Chapitre 2: Conteneurisation Docker

Introduction​

Docker permet d'empaqueter votre application avec toutes ses dépendances. "Ça marche sur ma machine" devient "Ça marche partout".


🎯 Objectifs du Chapitre​

À la fin de ce chapitre, vous saurez:

  1. ✅ Créer un Dockerfile pour Spring Boot
  2. ✅ Optimiser avec multi-stage builds
  3. ✅ Utiliser Docker Compose
  4. ✅ Gérer les configurations
  5. ✅ Optimiser la taille des images

1. Dockerfile de Base​

Version Simple​

FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Build et Run​

# Compiler l'application
mvn clean package -DskipTests

# Construire l'image
docker build -t myapp:1.0 .

# Exécuter
docker run -p 8080:8080 myapp:1.0

2. Multi-Stage Build (Recommandé)​

Dockerfile Optimisé​

# ===== STAGE 1: Build =====
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app

# Copier les fichiers de dépendances d'abord (cache Docker)
COPY pom.xml .
RUN mvn dependency:go-offline -B

# Copier le code source et compiler
COPY src ./src
RUN mvn clean package -DskipTests

# ===== STAGE 2: Runtime =====
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app

# Créer un utilisateur non-root
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

# Copier le JAR du stage précédent
COPY --from=builder /app/target/*.jar app.jar

# Configuration
EXPOSE 8080
ENV JAVA_OPTS="-Xms256m -Xmx512m"

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Avantages du Multi-Stage​

Image simple:      ~500 MB (avec Maven + JDK)
Image multi-stage: ~200 MB (seulement JRE)
Image Alpine: ~150 MB (JRE Alpine minimal)

3. Dockerfile avec Layers​

Spring Boot 2.3+ supporte les layers pour un cache Docker optimisé:

# ===== STAGE 1: Build =====
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn clean package -DskipTests

# Extraire les layers
RUN java -Djarmode=layertools -jar target/*.jar extract

# ===== STAGE 2: Runtime =====
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

# Copier les layers (dans l'ordre de fréquence de changement)
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./

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

Activer les Layers​

<!-- pom.xml -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>

4. Docker Compose​

docker-compose.yml​

version: '3.8'

services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DATABASE_URL=jdbc:postgresql://db:5432/mydb
- DB_USERNAME=postgres
- DB_PASSWORD=secret
depends_on:
db:
condition: service_healthy
networks:
- backend

db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=secret
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
networks:
- backend

volumes:
postgres_data:

networks:
backend:
driver: bridge

Commandes Docker Compose​

# Démarrer tous les services
docker-compose up -d

# Voir les logs
docker-compose logs -f app

# Arrêter
docker-compose down

# Reconstruire
docker-compose up -d --build

5. Profil Docker​

application-docker.properties​

# Configuration pour Docker
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

# Flyway
spring.flyway.enabled=true

# Actuator
management.endpoints.web.exposure.include=health,info,prometheus

# Logging
logging.level.root=INFO

6. .dockerignore​

# Build
target/
!target/*.jar

# IDE
.idea/
*.iml
.vscode/

# Git
.git/
.gitignore

# Docker
Dockerfile
docker-compose*.yml
.dockerignore

# Logs
*.log
logs/

# Tests
src/test/

7. Optimisations​

Image Alpine (plus légère)​

FROM eclipse-temurin:17-jre-alpine

Utilisateur Non-Root​

RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring

Health Check​

HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
CMD wget --quiet --tries=1 --spider http://localhost:8080/actuator/health || exit 1

Limites de Ressources​

# docker-compose.yml
services:
app:
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M

8. Docker Build avec BuildKit​

Activer BuildKit​

# Variable d'environnement
export DOCKER_BUILDKIT=1
docker build -t myapp .

# Ou dans Docker Desktop: Settings > Docker Engine
{
"features": {
"buildkit": true
}
}

Cache des Dépendances Maven​

FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app

# Cache des dépendances avec BuildKit
COPY pom.xml .
RUN --mount=type=cache,target=/root/.m2 mvn dependency:go-offline -B

COPY src ./src
RUN --mount=type=cache,target=/root/.m2 mvn clean package -DskipTests

9. Commandes Utiles​

Build​

# Build simple
docker build -t myapp:latest .

# Build avec tag
docker build -t myapp:1.0.0 -t myapp:latest .

# Build sans cache
docker build --no-cache -t myapp .

# Build avec arguments
docker build --build-arg JAR_FILE=target/*.jar -t myapp .

Run​

# Run basique
docker run -p 8080:8080 myapp

# Run en arrière-plan
docker run -d -p 8080:8080 --name myapp-container myapp

# Run avec variables d'environnement
docker run -d -p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e DATABASE_URL=jdbc:postgresql://host:5432/db \
myapp

# Run avec fichier .env
docker run -d -p 8080:8080 --env-file .env myapp

Debug​

# Logs
docker logs myapp-container
docker logs -f myapp-container # Follow

# Shell dans le conteneur
docker exec -it myapp-container sh

# Inspecter
docker inspect myapp-container

10. Résumé​

Dockerfile Recommandé​

FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn clean package -DskipTests

FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Checklist Docker​

□ Multi-stage build
□ Image Alpine (légère)
□ Utilisateur non-root
□ .dockerignore configuré
□ Variables d'environnement pour secrets
□ Health check
□ docker-compose pour dev local

🎯 Prochaine Étape​

L'image Docker est prête. Automatisons le build et le déploiement avec CI/CD!

➡️ Chapitre 3: CI/CD avec GitHub Actions


⬅️ Retour au Module 12