Introduction
Mettre à niveau ou migrer des conteneurs Docker ne consiste pas simplement à récupérer une image plus récente et à redémarrer le conteneur. Mal exécutée, l'opération peut entraîner une perte de données, une dérive de configuration, des échecs de compatibilité silencieux ou des temps d'arrêt prolongés. Correctement menée, elle se déroule comme une séquence contrôlée d'observation, de changement ciblé, de vérification et de récupération.
Ce guide présente un flux de travail pratique de mise à niveau et de migration pour les conteneurs Docker, destiné aux développeurs, ingénieurs DevOps et équipes techniques de startups. Nous couvrons l'inventaire des versions, la gestion sûre de la configuration, les vérifications préalables, les étapes de migration avec des commandes concrètes, la vérification, la restauration et les pièges courants. Chaque étape inclut des commandes exécutables, les sorties attendues, les signaux d'échec et les actions de récupération afin que vous puissiez appliquer directement le processus à votre environnement.
Le principe fondamental est la sécurité opérationnelle : observer avant de changer, limiter le rayon d'impact, garder les secrets hors de la ligne de commande, vérifier à chaque étape et toujours disposer d'un chemin de restauration testé.
Inventaire des versions et de l'environnement
Commencez par comprendre exactement ce que vous exécutez. Il s'agit d'une activité en lecture seule ; ne modifiez encore rien.
Vérifier les versions de Docker et Compose
docker version --format '{{.Server.Version}}'
docker compose version
Exemple de sortie :
24.0.7
Docker Compose version v2.21.0
Si vous utilisez un moteur Docker ou un format de fichier Compose plus ancien, la mise à niveau du conteneur peut nécessiter d'abord celle des outils de l'hôte. Par exemple, la version 3.x du fichier Compose requiert Docker Engine 1.13.0+ ; certaines syntaxes plus récentes (comme depends_on avec conditions) nécessitent Compose v2.20+.
Lister les conteneurs et images en cours d'exécution
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
docker images
Notez quels conteneurs sont gérés par Compose et lesquels sont autonomes. Pour les projets Compose, utilisez toujours les commandes docker compose pour garantir que l'état souhaité est appliqué de manière cohérente.
Inspecter la configuration critique
docker inspect <conteneur> --format '{{json .Mounts}}' | jq
docker inspect <conteneur> --format '{{json .Config.Env}}' | jq
docker inspect <conteneur> --format '{{json .Config.Labels}}' | jq
Remplacez <conteneur> par le nom ou l'identifiant réel. Cela affiche les volumes, les montages de liaison, les variables d'environnement et les libellés. Accordez une attention particulière à :
- Volumes et montages de liaison : les volumes nommés (par exemple,
app_data:/var/lib/app) sont gérés par Docker et plus faciles à sauvegarder/restaurer ; les montages de liaison (par exemple,./data:/var/lib/app) mappent des chemins de l'hôte et peuvent causer des problèmes de portabilité ou de permissions sur d'autres hôtes. - Variables d'environnement : n'exposez pas de secrets dans la commande. Utilisez un fichier d'environnement ou un gestionnaire de secrets.
- Healthcheck : si l'image définit un healthcheck, notez-le ; nous l'utiliserons pour la vérification ultérieure.
Savoir où vivent les données
Avant toute mise à niveau ou migration, vérifiez que les données de votre application sont persistantes et ne sont pas écrites dans la couche inscriptible du conteneur. Un test rapide :
docker stop <conteneur>
docker rm <conteneur>
docker run -d --name <conteneur> [mêmes options] <image>
docker exec <conteneur> ls /var/lib/app
Si des fichiers apparaissent, les données sont persistantes. Si le répertoire est vide, l'application écrivait dans le système de fichiers du conteneur et perdra des données à chaque recréation. Corrigez cela en ajoutant un volume avant de continuer.
Chemin de configuration sûr
Traitez la configuration comme du code. Conservez la configuration dans des fichiers sous contrôle de version, injectez-la via des variables d'environnement ou des fichiers de configuration montés, et ne codez jamais les secrets en dur.
Extraire la configuration actuelle
Pour un conteneur existant, exportez sa configuration pour examen :
docker inspect <conteneur> --format '{{json .Config}}' | jq > configuration-conteneur.json
Passez en revue le JSON. Notez le healthcheck, le point d'entrée, la commande, l'environnement et les volumes. Pour les services Compose, le fichier docker-compose.yml est la source de vérité ; assurez-vous qu'il correspond à la réalité.
Préparer la nouvelle configuration
Créez ou mettez à jour les fichiers de configuration dans un répertoire sûr. Exemple de docker-compose.yml pour une application web :
services:
web:
image: nginx:1.25
ports:
- "8080:80"
environment:
- NGINX_HOST=exemple.com
- NGINX_PORT=80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- app_data:/usr/share/nginx/html
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
volumes:
app_data:
Remarquez le healthcheck ; il sera utilisé pour la vérification.
Gestion des secrets
Ne transmettez jamais de secrets via -e sur la ligne de commande ni ne les commitez dans des fichiers. Utilisez les secrets Docker (pour Swarm), un fichier .env non suivi par le contrôle de version, ou un gestionnaire de secrets. Par exemple, avec un fichier .env :
echo "DB_PASSWORD=$(openssl rand -hex 16)" >> .env
Puis référencez-le dans Compose :
environment:
DB_PASSWORD: ${DB_PASSWORD}
Assurez-vous que .env figure dans .gitignore.
Valider la configuration
Pour les fichiers Compose :
docker compose config
Cela analyse et valide le fichier, fusionne les surcharges et affiche la configuration finale. Corrigez tout avertissement avant de continuer.
Étapes de migration et de mise à niveau
Nous pouvons maintenant procéder à la mise à niveau ou à la migration réelle. Nous supposons un scénario typique : mise à niveau d'un conteneur d'application de la version 1.0 à la version 2.0, éventuellement avec un changement de configuration, et déplacement d'un hôte à un autre. Les étapes sont similaires pour les deux.
1. Récupérer la nouvelle image
docker pull monapp:2.0
Vérifiez le condensat pour vous assurer d'avoir la bonne image :
docker images --digests
2. Tester la nouvelle image isolément
Exécutez la nouvelle image sur un port différent ou avec un nom de conteneur temporaire pour éviter de perturber le service en cours.
docker run -d --name monapp-test -p 8081:80 --env-file .env monapp:2.0
Dirigez un peu de trafic de test vers elle ou lancez des tests de fumée manuellement. Consultez les journaux :
docker logs monapp-test --tail 50
Si l'application comporte des migrations de base de données, exécutez-les d'abord sur une copie de la base de données.
3. Sauvegarder les données et la configuration
Avant de basculer le trafic, sauvegardez les volumes et la configuration actuelle.
Pour un volume nommé :
docker run --rm -v app_data:/data -v $(pwd):/backup alpine tar czf /backup/app_data_backup_$(date +%Y%m%d_%H%M%S).tar.gz -C /data .
Pour les montages de liaison, faites simplement cp -a du répertoire.
Enregistrez également la configuration du conteneur actuel :
docker inspect monapp > monapp_config_actuelle_$(date +%Y%m%d).json
4. Mettre à jour le service
Si vous utilisez Compose, modifiez l'étiquette de l'image dans docker-compose.yml, puis exécutez :
docker compose up -d --no-deps monapp
L'option --no-deps évite de recréer inutilement les conteneurs dépendants.
Si le conteneur est autonome, arrêtez, supprimez et recréez :
docker stop monapp
docker rm monapp
docker run -d --name monapp [mêmes options mais nouvelle image] monapp:2.0
5. Vérifier la nouvelle version
Vérifiez que le conteneur fonctionne et qu'il est sain :
docker ps --filter name=monapp
Recherchez le passage du statut de santé à healthy. Si votre image n'a pas de healthcheck, utilisez celui noté précédemment ou vérifiez manuellement les journaux et les points de terminaison de l'application.
Pour Compose :
docker compose ps
Consultez les journaux de l'application :
docker logs monapp --tail 50
Surveillez toute nouvelle erreur ou tout nouvel avertissement.
6. Scénario de migration : déplacement vers un nouvel hôte
Si vous migrez vers un nouvel hôte, après avoir effectué la sauvegarde, transférez la sauvegarde et la configuration vers le nouvel hôte. Les options incluent scp, rsync ou le stockage d'objets.
Sur le nouvel hôte, assurez-vous que les versions de Docker et Compose sont compatibles. Restaurez les données du volume :
docker volume create app_data
docker run --rm -v app_data:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/app_data_backup_*.tar.gz"
Démarrez ensuite le service avec la configuration mise à jour. Testez minutieusement avant de mettre hors service l'ancien hôte.
Vérification et diagnostics
Après la mise à niveau ou la migration, vérifiez non seulement que le conteneur fonctionne, mais aussi que l'application se comporte correctement.
Points de terminaison de healthcheck
Si votre application expose un point de terminaison de santé, utilisez curl ou un script :
curl -f http://localhost:8080/health
Sortie attendue : OK ou similaire.
Vérifier l'utilisation des ressources du conteneur
docker stats --no-stream monapp
Comparez l'utilisation du CPU et de la mémoire avec la version précédente pour détecter les régressions.
Inspecter les journaux à la recherche d'erreurs
docker logs monapp --since 30m | grep -i error
Aucune sortie signifie aucune erreur au cours des 30 dernières minutes.
Exécuter des tests de fumée automatisés
Si vous disposez de tests d'intégration ou de scripts, exécutez-les contre le nouveau service. Par exemple, une simple boucle curl :
for i in {1..5}; do curl -s http://localhost:8080/api/items | jq .; sleep 2; done
Vérifiez que les réponses sont conformes aux attentes.
Comparer la configuration
Utilisez docker inspect et comparez avec le JSON enregistré pour vous assurer qu'il n'y a pas de changements non intentionnels :
diff <(docker inspect monapp --format '{{json .Config.Env}}' | jq -S .) <(jq -S '.[0].Config.Env' monapp_config_actuelle.json)
Ajustez l'expression jq selon la structure du fichier enregistré.
Modes de défaillance et récupération
Même avec une planification minutieuse, des échecs surviennent. Voici les modes de défaillance courants, comment les détecter et les actions de récupération.
Échec de récupération de l'image
Symptôme : docker pull renvoie des erreurs d'authentification ou de réseau.
Récupération : Vérifiez les informations d'identification du registre (docker login), la connectivité réseau, le DNS et l'espace disque disponible (df -h). Si l'image n'est pas disponible, restaurez à partir de la sauvegarde ou utilisez la version précédente.
Le conteneur ne démarre pas
Symptôme : docker run ou docker compose up se termine avec un code non nul.
Diagnostic : Consultez docker logs pour les erreurs d'application. Vérifiez que les volumes ou variables d'environnement requis sont présents. Comparez avec la configuration du conteneur précédent.
Récupération : Si le problème vient de la configuration, corrigez et relancez. Si la nouvelle image est défectueuse, revenez à l'image précédente (voir ci-dessous).
L'application démarre mais se comporte incorrectement
Symptôme : Le healthcheck échoue, les points de terminaison renvoient des erreurs ou les données sont absentes.
Diagnostic : Vérifiez les journaux, la connectivité de la base de données et les montages de volumes. Si des données sont absentes, vérifiez que les volumes sont correctement attachés et non vides.
Récupération : Revenez à la version précédente, puis enquêtez.
Perte ou corruption des données
Symptôme : Répertoires vides, erreurs de base de données ou fichiers manquants.
Prévention : Toujours sauvegarder avant d'apporter des modifications.
Récupération : Restaurez à partir de la sauvegarde dès que possible. Pour éviter de futurs problèmes, utilisez des volumes nommés ou des montages de liaison et testez la persistance avant le déploiement.
Procédure de restauration
Ayez toujours un plan de restauration. Pour Compose :
docker compose down
git checkout <commit-précédent> # si la configuration est sous contrôle de version
docker compose up -d
Si vous utilisez une étiquette d'image précédente, revenez à cette étiquette et relancez up.
Pour les conteneurs autonomes :
docker stop monapp
docker rm monapp
docker run -d --name monapp [mêmes options que l'original] monapp:1.0
Restaurez les données à partir de la sauvegarde si nécessaire.
Pièges courants
Voici les pièges qui causent souvent des échecs de mise à niveau ou de migration, avec leurs raisons et comment les éviter.
1. Sauter la sauvegarde
Pourquoi cela arrive : Excès de confiance ou pression temporelle. Comment éviter : Faites de la sauvegarde une étape obligatoire de votre procédure. Automatisez-la si possible.
2. Changer trop de choses à la fois
Pourquoi cela arrive : Combiner la mise à niveau de l'image, les changements de configuration et les déplacements d'environnement en une seule grande étape. Comment éviter : Séparez les changements en étapes distinctes et vérifiables indépendamment. Par exemple, migrez d'abord avec la même version, puis mettez à niveau l'image.
3. Ne pas tester la persistance des données
Pourquoi cela arrive : Supposer que l'application est configurée pour utiliser des volumes sans vérifier. Comment éviter : Effectuez le test de redémarrage décrit dans la section d'inventaire. Assurez-vous que les données survivent à la recréation du conteneur.
4. Coder en dur les secrets dans la configuration ou les commandes
Pourquoi cela arrive : Commodité ou manque de sensibilisation. Comment éviter : Utilisez des fichiers d'environnement, des secrets Docker ou un gestionnaire de secrets. Ne commitez jamais de secrets dans le contrôle de version.
5. Ignorer le statut du healthcheck
Pourquoi cela arrive : Se fier uniquement à l'état « en cours d'exécution » du conteneur. Comment éviter : Définissez un healthcheck robuste pour votre application et surveillez-le pendant et après la mise à niveau.
6. Ne pas avoir de plan de restauration
Pourquoi cela arrive : Biais d'optimisme ou manque de préparation. Comment éviter : Notez les commandes exactes de restauration avant de commencer la mise à niveau. Testez la restauration dans un environnement de préproduction.
Liste de contrôle des opérations
Utilisez cette liste de contrôle avant, pendant et après toute mise à niveau ou migration de conteneur Docker. Attribuez chaque élément à un seul responsable (par exemple, un ingénieur spécifique) et passez en revue la liste au début et à la fin de l'opération. Pour les mises à niveau de routine, examinez-la mensuellement pour vous assurer qu'elle reste à jour.
| Étape | Action | Responsable (exemple) | Vérification |
|---|---|---|---|
| Pré-vol | Vérifier les versions de Docker/Compose et les prérequis | Priya Shah, responsable DevOps | Les sorties de docker version, docker compose version correspondent aux exigences |
| Inventaire | Lister les conteneurs, images, montages et environnement | Alex Chen, ingénieur d'exploitation | Enregistrements de docker ps, docker inspect sauvegardés |
| Configuration | Extraire et examiner la configuration actuelle | Maria Gomez, développeuse d'applications | Fichier JSON/Compose examiné et sauvegardé |
| Sauvegarde | Sauvegarder les volumes et la configuration | Alex Chen, ingénieur d'exploitation | Les fichiers de sauvegarde existent et sont lisibles |
| Test | Exécuter la nouvelle image dans un conteneur isolé | Maria Gomez, développeuse d'applications | Les tests de fumée passent, les journaux sont propres |
| Changement | Mettre à jour le service vers la nouvelle image avec les changements de configuration | Priya Shah, responsable DevOps | docker compose up -d réussit |
| Vérification | Vérifier la santé du conteneur, les journaux, les points de terminaison | Alex Chen, ingénieur d'exploitation | Healthcheck healthy, les points de terminaison renvoient les données attendues |
| Restauration (si nécessaire) | Exécuter la procédure de restauration documentée | Priya Shah, responsable DevOps | Service restauré à la version précédente, vérifié |
| Revue post-opération | Documenter ce qui s'est passé, les leçons apprises | Tous les responsables | Minutes de la réunion de revue, procédure mise à jour |
Fréquence de revue : Pour les services de production, examinez cette liste de contrôle avec l'équipe mensuellement ou avant chaque mise à niveau majeure. Pour les migrations trimestrielles ou ponctuelles, examinez-la au début du projet de migration.
Conclusion
Mettre à niveau et migrer des conteneurs Docker en toute sécurité est un processus discipliné qui combine préparation, exécution et vérification. En suivant les étapes décrites ici — inventorier votre environnement, gérer la configuration avec soin, sauvegarder les données, tester avant la bascule, vérifier après le changement et disposer d'un plan de restauration — vous pouvez éviter les pièges courants et maintenir la fiabilité de vos services.
Rappelez-vous : chaque commande exécutée doit avoir un résultat attendu connu et un chemin de récupération si le résultat est différent. Traitez votre infrastructure de conteneurs comme du bétail, pas comme des animaux de compagnie, mais gardez les données et la configuration précieuses. Avec de bonnes pratiques, les mises à niveau et les migrations deviennent des opérations de routine plutôt que des événements risqués.
Comme prochaine étape, choisissez un conteneur à faible risque dans votre environnement et passez par les étapes d'inventaire et de sauvegarde. Créez ensuite un plan pour sa mise à niveau à l'aide de la liste de contrôle. Gagnez en confiance dans le processus avant de vous attaquer aux charges de travail critiques.