## 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 ```bash docker version --format '{{.Server.Version}}' docker compose version ``` Exemple de sortie : ```text 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 ```bash 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 ```bash docker inspect --format '{{json .Mounts}}' | jq docker inspect --format '{{json .Config.Env}}' | jq docker inspect --format '{{json .Config.Labels}}' | jq ``` Remplacez `` 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 : ```bash docker stop docker rm docker run -d --name [mêmes options] docker exec 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 : ```bash docker inspect --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 : ```yaml 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` : ```bash echo "DB_PASSWORD=$(openssl rand -hex 16)" >> .env ``` Puis référencez-le dans Compose : ```yaml environment: DB_PASSWORD: ${DB_PASSWORD} ``` Assurez-vous que `.env` figure dans `.gitignore`. ### Valider la configuration Pour les fichiers Compose : ```bash 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 ```bash docker pull monapp:2.0 ``` Vérifiez le condensat pour vous assurer d'avoir la bonne image : ```bash 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. ```bash 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 : ```bash 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é : ```bash 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 : ```bash 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 : ```bash 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 : ```bash 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 : ```bash 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 : ```bash docker compose ps ``` Consultez les journaux de l'application : ```bash 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 : ```bash 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 : ```bash curl -f http://localhost:8080/health ``` Sortie attendue : `OK` ou similaire. ### Vérifier l'utilisation des ressources du conteneur ```bash 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 ```bash 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 : ```bash 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 : ```bash 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 : ```bash docker compose down git checkout # 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 : ```bash 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.