Spring Boot en production : Checklist de déploiement
Ton application Spring Boot fonctionne parfaitement en local. Tu es prêt à la déployer en production !
Mais attends... As-tu pensé à :
- Sécuriser tes endpoints ?
- Configurer les logs pour la production ?
- Optimiser les performances ?
- Mettre en place du monitoring ?
Déployer en production sans préparation, c'est comme sauter en parachute sans vérifier le parachute. Ça peut marcher... ou pas.
Dans cet article, nous allons voir tout ce qu'il faut vérifier avant de déployer en production. Cette checklist t'évitera 99% des problèmes courants.
Contexte technique
Versions utilisées :
- Spring Boot 3.2+
- Java 17+
- Spring Security pour la sécurité
- Spring Boot Actuator pour le monitoring
- Micrometer pour les métriques
Sommaire
- Sécurité
- Configuration
- Base de données
- Logs et monitoring
- Performance
- Résilience
- Tests
- Documentation
- Déploiement
- Post-déploiement
Sécurité
✅ Checklist Sécurité
1. Activer HTTPS
Pourquoi ? Sans HTTPS, toutes les données (mots de passe, tokens, etc.) circulent en clair sur le réseau.
Comment ?
# application-prod.yml
server:
port: 443
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: ${SSL_KEYSTORE_PASSWORD}
key-store-type: PKCS12Alternative : Utilisez un reverse proxy (Nginx, Traefik) qui gère le SSL.
2. Configurer Spring Security
Minimum requis :
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/public/**").permitAll() // Endpoints publics
.requestMatchers("/actuator/health").permitAll() // Health check
.anyRequest().authenticated() // Tout le reste nécessite une authentification
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt()); // Si vous utilisez JWT
return http.build();
}
}Conseil : Utilisez OAuth2/JWT pour l'authentification des API REST.
3. Valider TOUTES les entrées utilisateur
Mauvais :
@PostMapping("/users")
public User createUser(@RequestBody CreateUserRequest request) {
// Pas de validation, accepte n'importe quoi
return userService.createUser(request);
}Bon :
@PostMapping("/users")
public User createUser(@Valid @RequestBody CreateUserRequest request) {
// @Valid active la validation automatique
return userService.createUser(request);
}4. Protéger contre les injections SQL
Mauvais :
String query = "SELECT * FROM users WHERE email = '" + email + "'"; // Injection SQL possible !Bon :
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email); // Paramètre sécuriséEncore mieux : Utilisez Spring Data JPA qui protège automatiquement.
Optional<User> findByEmail(String email); // Sécurisé par défaut5. Ne JAMAIS exposer les secrets dans le code
Mauvais :
spring:
datasource:
password: SuperMotDePasseSecret123 # 🚨 Visible dans Git !Bon :
spring:
datasource:
password: ${DATABASE_PASSWORD} # Variable d'environnement6. Configurer CORS correctement
Mauvais :
@CrossOrigin(origins = "*") // Accepte TOUTES les origines !Bon :
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://monsite.com", "https://www.monsite.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true);
}
};
}
}7. Désactiver les endpoints sensibles
# application-prod.yml
spring:
h2:
console:
enabled: false # Jamais en production !
management:
endpoints:
web:
exposure:
include: health,info # Seulement les endpoints nécessairesConfiguration
✅ Checklist Configuration
1. Profil de production actif
Vérifiez que le profil prod est bien actif :
export SPRING_PROFILES_ACTIVE=prodOu dans le script de démarrage :
java -jar app.jar --spring.profiles.active=prod2. Désactiver ddl-auto
CRITIQUE : Ne JAMAIS utiliser create-drop ou update en production.
# application-prod.yml
spring:
jpa:
hibernate:
ddl-auto: none # ⚠️ Très important !Pourquoi ?
create-dropsupprime toutes les données au redémarrageupdatepeut corrompre la base en production
Solution : Utilisez Flyway ou Liquibase pour gérer les migrations.
3. Configurer les timeouts
spring:
datasource:
hikari:
connection-timeout: 30000 # 30 secondes
maximum-pool-size: 20
minimum-idle: 54. Désactiver les logs SQL
spring:
jpa:
show-sql: false # Ralentit l'application5. Configuration du serveur
server:
port: ${SERVER_PORT:8080}
shutdown: graceful # Graceful shutdown
tomcat:
threads:
max: 200
min-spare: 10Base de données
✅ Checklist Base de données
1. Utiliser une vraie base de données
Mauvais :
# En production avec H2 en mémoire = DÉSASTRE !
spring:
datasource:
url: jdbc:h2:mem:testdbBon :
spring:
datasource:
url: ${DATABASE_URL}
driver-class-name: org.postgresql.Driver2. Pool de connexions optimisé
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
max-lifetime: 1800000 # 30 minutes
connection-timeout: 30000
idle-timeout: 600000 # 10 minutesCalcul du pool : max_pool_size = nombre_de_threads_tomcat / nombre_de_services
3. Migrations versionnées
Utilisez Flyway ou Liquibase.
Exemple avec Flyway :
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>-- src/main/resources/db/migration/V1__initial_schema.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(100) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP
);4. Sauvegardes automatiques
Configurez des sauvegardes automatiques de votre base :
- Fréquence : Quotidienne minimum, idéalement plusieurs fois par jour
- Rétention : Au moins 7 jours
- Testez les restaurations régulièrement
5. Indexes sur les colonnes fréquemment requêtées
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_user_id ON orders(user_id);Comment savoir quels index créer ?
- Analysez les requêtes lentes avec
EXPLAIN ANALYZE - Indexez les colonnes dans les
WHERE,JOIN,ORDER BY
Logs et monitoring
✅ Checklist Logs
1. Configurer les niveaux de logs
# application-prod.yml
logging:
level:
root: WARN # Logs minimaux
com.springcraft: INFO # Votre code en INFO
org.springframework: WARN
org.hibernate: WARN
file:
name: /var/log/springcraft/application.log
max-size: 10MB
max-history: 30 # Garde 30 joursPourquoi pas DEBUG en prod ?
- Les logs DEBUG sont très verbeux
- Ralentissent l'application
- Remplissent rapidement le disque
2. Logs structurés (JSON)
Utilisez un format JSON pour faciliter l'analyse :
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.3</version>
</dependency><!-- logback-spring.xml -->
<configuration>
<appender name="JSON" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/springcraft/application.log</file>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="JSON"/>
</root>
</configuration>3. Activer Spring Boot Actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when-authorized
metrics:
export:
prometheus:
enabled: trueEndpoints utiles :
/actuator/health: État de l'application/actuator/metrics: Métriques (mémoire, CPU, requêtes, etc.)/actuator/prometheus: Métriques au format Prometheus
4. Monitoring avec Prometheus + Grafana
- Prometheus : Collecte les métriques
- Grafana : Visualise les métriques
Dashboard Grafana recommandé : Spring Boot 2.1 Statistics (ID : 10280)
5. Alertes
Configurez des alertes pour :
- ❌ Application down
- 💥 Taux d'erreur > 5%
- 🐌 Temps de réponse > 2 secondes
- 💾 Mémoire > 80%
- 💿 Disque > 90%
Performance
✅ Checklist Performance
1. Activer le cache
spring:
cache:
type: redis # Ou caffeine pour un cache local@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public UserDTO getUserById(Long id) {
// Résultat mis en cache
return userRepository.findById(id)...
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
// Invalide le cache
userRepository.deleteById(id);
}
}2. Optimiser les requêtes JPA
Problème N+1 :
Mauvais :
List<User> users = userRepository.findAll(); // 1 requête
for (User user : users) {
user.getOrders().size(); // N requêtes (1 par utilisateur) !
}Bon :
@Query("SELECT u FROM User u LEFT JOIN FETCH u.orders")
List<User> findAllWithOrders(); // 1 seule requête3. Pagination
Ne renvoyez jamais tous les résultats d'un coup :
@GetMapping("/users")
public Page<UserDTO> getAllUsers(Pageable pageable) {
return userService.getAllUsers(pageable);
}Utilisation : GET /api/users?page=0&size=20
4. Compression des réponses
server:
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/xml,text/plain5. Configuration JVM
java -Xms512m -Xmx2g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-jar app.jarExplication :
-Xms512m: Heap initial de 512 Mo-Xmx2g: Heap max de 2 Go-XX:+UseG1GC: Utilise le garbage collector G1 (recommandé)-XX:MaxGCPauseMillis=200: Pause GC max de 200ms
Résilience
✅ Checklist Résilience
1. Health checks
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
@Autowired
private DataSource dataSource;
@Override
public Health health() {
try {
dataSource.getConnection().close();
return Health.up().build();
} catch (Exception e) {
return Health.down().withException(e).build();
}
}
}2. Retry automatique
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>@Service
public class ExternalApiService {
@Retryable(
value = { RestClientException.class },
maxAttempts = 3,
backoff = @Backoff(delay = 1000)
)
public String callExternalApi() {
// Retry automatique en cas d'échec
return restTemplate.getForObject("https://api.example.com/data", String.class);
}
}3. Circuit breaker
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
</dependency>@Service
public class ExternalApiService {
@CircuitBreaker(name = "externalApi", fallbackMethod = "fallback")
public String callExternalApi() {
return restTemplate.getForObject("https://api.example.com/data", String.class);
}
public String fallback(Exception e) {
return "Service temporairement indisponible";
}
}4. Graceful shutdown
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30sEffet : Quand vous arrêtez l'application, Spring attend que toutes les requêtes en cours se terminent (max 30s).
Tests
✅ Checklist Tests
1. Couverture de code > 80%
Utilisez JaCoCo pour mesurer la couverture :
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>Générer le rapport : mvn jacoco:report
2. Tests unitaires pour la logique métier
Minimum : Testez tous vos services.
3. Tests d'intégration pour les endpoints
Testez au moins les endpoints critiques (création, authentification, etc.).
4. Tests de charge (si forte volumétrie)
Utilisez JMeter, Gatling ou k6 pour simuler du trafic.
Documentation
✅ Checklist Documentation
1. README complet
Incluez :
- Description du projet
- Comment installer les dépendances
- Comment lancer en local
- Comment déployer
- Variables d'environnement requises
2. Documentation API
Utilisez Swagger/OpenAPI :
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</dependency>Accès : http://localhost:8080/swagger-ui.html
3. Diagrammes d'architecture
Créez au moins :
- Schéma de l'architecture globale
- Diagramme de la base de données
Déploiement
✅ Checklist Déploiement
1. CI/CD configuré
Automatisez le déploiement avec GitHub Actions, GitLab CI, Jenkins, etc.
Exemple GitHub Actions :
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
- name: Build
run: mvn clean package
- name: Deploy
run: ./deploy.sh2. Blue/Green ou Canary deployment
Ne déployez jamais directement en production. Utilisez :
- Blue/Green : Deux environnements identiques, switch instantané
- Canary : Déploiement progressif (10% du trafic, puis 50%, puis 100%)
3. Rollback facile
Gardez toujours la possibilité de revenir à la version précédente en 1 clic.
Post-déploiement
✅ Checklist Post-déploiement
1. Smoke tests
Vérifiez immédiatement après le déploiement :
- L'application démarre
- Les endpoints critiques fonctionnent
- La base de données est accessible
2. Monitoring des logs
Surveillez les logs pendant les premières heures pour détecter des erreurs.
3. Alertes configurées
Vérifiez que vous recevez les alertes (email, Slack, PagerDuty, etc.).
Checklist complète (résumé)
Sécurité
- HTTPS activé
- Spring Security configuré
- Validation sur tous les endpoints
- Pas d'injection SQL
- Secrets externalisés
- CORS configuré correctement
Configuration
- Profil
prodactif -
ddl-auto: none - Timeouts configurés
- Logs SQL désactivés
Base de données
- Base de données persistante (pas H2)
- Pool de connexions optimisé
- Migrations versionnées (Flyway/Liquibase)
- Sauvegardes automatiques
- Indexes créés
Logs et Monitoring
- Logs en niveau INFO/WARN
- Actuator activé
- Prometheus/Grafana configuré
- Alertes configurées
Performance
- Cache activé
- Requêtes JPA optimisées
- Pagination activée
- Compression activée
- JVM configurée
Résilience
- Health checks configurés
- Retry activé
- Circuit breaker configuré
- Graceful shutdown activé
Tests
- Couverture > 80%
- Tests unitaires
- Tests d'intégration
- Tests de charge (si nécessaire)
Documentation
- README complet
- Documentation API (Swagger)
- Diagrammes d'architecture
Déploiement
- CI/CD configuré
- Blue/Green ou Canary
- Rollback facile
Post-déploiement
- Smoke tests effectués
- Logs surveillés
- Alertes testées
Pour aller plus loin
Félicitations ! Vous avez maintenant une checklist complète pour déployer en production en toute sérénité. 🎉
📚 Série d'articles complémentaires
- Comment structurer un projet Spring Boot - Les fondations
- Tests dans Spring Boot : Guide complet - Testez avant de déployer
- Configuration multi-environnements - Séparez dev/test/prod
- Gestion des exceptions dans Spring Boot - Gérez les erreurs proprement
- CRUD complet avec Spring Boot - Un exemple complet
🎯 Points clés à retenir
- Sécurisez tout : HTTPS, secrets, validation
- Monitorer : Logs, métriques, alertes
- Optimisez : Cache, pagination, requêtes
- Testez : Unitaire, intégration, charge
- Automatisez : CI/CD, déploiement, rollback
- Documentez : README, API, architecture
Déployer en production, ce n'est pas juste lancer l'application. C'est s'assurer qu'elle fonctionne bien, qu'elle est sécurisée, qu'elle performe, et qu'on peut la débugger facilement.
Bon déploiement ! 🚀