Docker Production Pattern
Contexte
Docker est largement utilisé pour déployer des applications backend modernes. Il permet d'encapsuler une application et ses dépendances dans un conteneur portable.
Cependant, un conteneur utilisé en production doit être construit différemment d'un conteneur de développement.
Les objectifs principaux sont :
- sécurité
- reproductibilité
- performance
- isolation
Une mauvaise configuration peut exposer le système à des vulnérabilités ou compliquer la maintenance.
Principe
Le pattern "Docker Production" consiste à construire des images conteneurisées :
- minimalistes
- sécurisées
- reproductibles
Cela implique plusieurs bonnes pratiques.
Multi-stage Build
Les images Docker doivent être construites en plusieurs étapes.
Objectif :
- séparer la phase de build
- produire une image finale minimale
Exemple :
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM eclipse-temurin:21-jre
COPY --from=build /app/target/app.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Avantages
- image plus petite
- moins de dépendances
- surface d’attaque réduite
Utilisateur non-root
Les conteneurs ne doivent pas s'exécuter avec l'utilisateur root.
Exemple :
RUN useradd -u 10001 appuser
USER appuser
Avantages
- limite les privilèges
- réduit les risques en cas de compromission
Filesystem en lecture seule
En production, le filesystem du conteneur peut être configuré en lecture seule.
Exemple dans docker-compose :
read_only: true
Cela empêche l'écriture de fichiers malveillants dans le conteneur.
Répertoires temporaires (tmpfs)
Les répertoires temporaires peuvent être placés en mémoire.
Exemple :
tmpfs:
/tmp
Avantages
- améliore les performances
- empêche la persistance de fichiers
Réseau Docker
Les services internes doivent communiquer via un réseau Docker interne.
Exemple :
networks:
backend-network
Les bases de données et brokers ne doivent pas être exposés publiquement.
Gestion des variables d’environnement
Les configurations doivent être injectées via des variables d’environnement.
Exemple :
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=postgres://...
Cela permet :
- de séparer configuration et code
- d’adapter facilement les environnements
Healthchecks
Les conteneurs doivent exposer un mécanisme de vérification de santé.
Exemple :
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
Les orchestrateurs peuvent utiliser ces informations pour redémarrer les conteneurs.
Logs
Les applications doivent écrire leurs logs sur la sortie standard.
Exemple :
stdout
stderr
Cela permet aux systèmes d’orchestration de collecter les logs.
Avantages
Cette approche apporte :
- sécurité renforcée
- images plus petites
- déploiements reproductibles
- meilleure observabilité
Limites
La configuration peut devenir plus complexe.
Certaines applications doivent être adaptées pour fonctionner avec un filesystem en lecture seule.
Conclusion
Docker est un outil puissant pour déployer des applications backend modernes.
En appliquant ces bonnes pratiques, il est possible de construire des conteneurs sécurisés, portables et adaptés à la production.