Prérequis
Pourr suivre ce guide, vous aurez besoin de :
- Docker Desktop (pour Windows/macOS) ou Docker Engine (pour Linux)
- Un projet Spring Boot 3.x existant
- Un JDK 17 ou supérieur
Structure du projet
Voici une structure de projet typique :
spring-boot-docker/
├── src/
├── Dockerfile
├── docker-compose.yml
└── .dockerignore
Création du Dockerfile
Un Dockerfile en deux étapes pour une image optimisée :
# Étape de construction
FROM maven:3.9-eclipse-temurin-17 AS construction
WORKDIR /opt/app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# Étape d'exécution
FROM eclipse-temurin:17-jre-alpine
WORKDIR /opt/app
# Sécurité : utilisateur non-root
RUN addgroup -S groupe-app && adduser -S utilisateur -G groupe-app
COPY --from=construction /opt/app/target/*.jar app.jar
RUN chown -R utilisateur:groupe-app /opt/app
USER utilisateur
# Paramètres JVM
ENV JVM_OPTS="-Xms256m -Xmx512m"
ENV SPRING_PROFILES_ACTIVE=production
# Vérification de santé
HEALTHCHECK --interval=45s --timeout=4s \
CMD wget -qO- http://localhost:8080/actuator/health > /dev/null || exit 1
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JVM_OPTS -jar app.jar"]
Fichier .dockerignore
Pour accélérer la consturction de l'image :
.git
*.iml
target/
*.md
Dockerfile
docker-compose.yml
log/
.idea/
Commandes de base Docker
Construire et gérer votre conteneur :
# Construction de l'image
docker build -t springboot-app:1.0 .
# Lancement du conteneur
docker run -d -p 8080:8080 --name mon-app springboot-app:1.0
# Consultation des logs
docker logs -f mon-app
# Connexion au conteneur
docker exec -it mon-app sh
Orchestration avec Docker Compose
Fichier de configuration complet avec une base de données :
version: '3.8'
services:
application:
build: .
container_name: spring-app
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=production
- SPRING_DATASOURCE_URL=jdbc:mysql://database:3306/appdb
- SPRING_DATASOURCE_USER=appuser
- SPRING_DATASOURCE_PASSWORD=secret
depends_on:
database:
condition: service_healthy
restart: always
networks:
- res-app
database:
image: mysql:8.0
container_name: mysql-server
environment:
MYSQL_ROOT_PASSWORD: rootsecret
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: secret
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 15s
timeout: 5s
retries: 3
networks:
- res-app
volumes:
db-data:
networks:
res-app:
driver: bridge
Conseils d'optimisation
1. Utilisation de registres miroirs
Configuration pour accélérer le téléchargement des images :
// /etc/docker/daemon.json
{
"registry-mirrors": ["https://mirror.example.com"]
}
2. Réduction de la taille de l'image
- Préférer les images Alpine Linux
- Séparer les phases de construction et d'exécution
- Utiliser un fichier .dockerignore complet
3. Bonnes pratiques de sécurité
- Toujours exécuter l'application avec un utilisateur non privilégié
- Limiter les ports exposés au strict nécessaire
- Ne jamais stocker de secrets dans les images
Dépannage courant
Problème : Impossible de joindre la base de données depuis le conteneur
Solution : Utiliser l'adresse DNS interne de Docker Compose
jdbc:mysql://database:3306/appdb
Problème : Erreurs OutOfMemoryError
Solution : Ajuster les limites mémoire de la JVM dans le Dockerfile
ENV JVM_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC"