Salut à tous, Le site fonctionnait, les pages répondaient, WordPress écrivait bien dans sa base et les voyants étaient au vert. Pourtant, le jour où j’ai voulu réaliser un dump MariaDB complet, celui-ci m’a répondu avec toute la délicatesse habituelle d’une base de données contrariée :
Column count of mysql.proc is wrong. Expected 22, found 21.
Created with MariaDB 110302, now running 120302.Le moteur MariaDB avait été mis à jour en version 12.3.2, mais certaines tables système du volume persistant étaient toujours au format 11.3.2. Le blog semblait en parfaite santé, alors que sa sauvegarde complète ne l’était plus. C’est précisément le genre de panne silencieuse que l’on préfère découvrir pendant un contrôle plutôt que pendant une restauration.
Bienvenue dans la douzième partie de ma série Docker et Portainer ! Celle où je reviens sur un conseil donné quelques années plus tôt, parce qu’un bon conseil d’administration système doit parfois accepter une mise à jour lui aussi.
Rappel des articles de la série « Docker et Portainer »
- Les conteneurs pour les débutants
- Créer une stack vsftpd mono-image
- Déployer une stack Docker Guacamole
- Docker, OpenVPN et Splunk
- Customiser un conteneur PHP-FPM
- Déployer Nextcloud avec Docker
- Mettre à jour Portainer et ses conteneurs
- Déployer Jitsi Meet avec Docker
- Superviser Docker avec Splunk
- Installer TheHive et Cortex avec Docker
- Installer OpenCTI avec Docker
- MariaDB, quand latest casse les sauvegardes
Pourquoi la mise à jour MariaDB Docker semblait-elle fonctionner ?
Une image Docker contient le logiciel MariaDB. Le volume, lui, conserve les données et les structures internes de la base. Dans la première partie de cette série, je vous expliquais justement qu’un volume survit au remplacement du conteneur. C’est vrai, et heureusement.
Mais survivre ne veut pas dire se convertir tout seul. Ici, Watchtower avait remplacé l’image mariadb:latest par une version majeure plus récente. Les tables WordPress ordinaires restaient lisibles, ce qui suffisait pour servir le site. Certaines opérations d’administration utilisant les tables système, notamment l’export des routines, échouaient en revanche immédiatement.
Les journaux MariaDB donnaient d’ailleurs la réponse : une mise à niveau était nécessaire, mais elle n’avait pas été exécutée. L’image officielle sait automatiser cette étape lorsque MARIADB_AUTO_UPGRADE est activé. Son script d’entrée officiel sauvegarde alors la base système avant de lancer la mise à niveau. Sans cette option, il ne modifie pas silencieusement le schéma persistant, ce qui est plutôt une sage précaution.
Le vrai problème : latest, Watchtower et une base persistante
Dans les articles consacrés à Guacamole et à Nextcloud, j’utilisais encore des références MariaDB flottantes. Puis, dans l’article sur Watchtower, je vous invitais presque à y aller les yeux fermés.
Bon, en 2026, ouvrez-en au moins un lorsque Watchtower s’approche d’une base de données.
Watchtower n’a pas inventé une mauvaise version et Docker n’a pas perdu les données. Chacun a fait exactement ce qu’on lui demandait :
latestautorisait le déplacement vers une nouvelle version majeure ;- Watchtower remplaçait automatiquement le conteneur lorsqu’une nouvelle image apparaissait ;
- le volume persistait avec son ancien schéma ;
- aucune procédure de migration applicative ne reliait ces trois opérations.
La règle que je retiens est donc simple : automatiser la détection largement, automatiser le remplacement sélectivement et migrer les services persistants volontairement.
Avant de réparer : construire un vrai rollback
Une mise à niveau modifie les structures internes de la base. Revenir ensuite à une ancienne image n’est donc pas un plan de rollback suffisant. Avant toute modification, j’ai créé deux niveaux de sauvegarde :
- des dumps logiques séparés des bases encore exportables ;
- un instantané physique du volume MariaDB, réalisé conteneur arrêté proprement.
Le dump global avec routines était justement l’opération en panne. Il ne fallait pas transformer cet échec en prétexte pour ne rien sauvegarder :
mariadb-dump --single-transaction --quick --triggers \
--databases wordpress > wordpress-before.sql
mariadb-dump --single-transaction --quick --triggers \
--databases mysql > mysql-before.sqlJ’ai ensuite arrêté les composants capables d’écrire dans WordPress, demandé à InnoDB une fermeture complète, puis arrêté MariaDB avant la copie physique :
docker stop <proxy-web> <php-wordpress>
docker exec <mariadb> mariadb --user=root \
-e "SET GLOBAL innodb_fast_shutdown=0;"
docker stop <mariadb>
# Copie ou snapshot du volume MariaDB iciLes identifiants doivent naturellement être fournis par un fichier de configuration protégé ou un secret (hein ;)), pas placés dans la ligne de commande. Les sauvegardes ont également été contrôlées et accompagnées de sommes de contrôle.
Terminer réellement la mise à jour MariaDB
La procédure officielle de changement de version majeure recommande justement de sauvegarder, d’arrêter proprement l’ancienne version, de démarrer la nouvelle, d’exécuter mariadb-upgrade, puis de contrôler les journaux.
Après redémarrage du seul conteneur MariaDB, j’ai donc exécuté la mise à niveau, puis redémarré une seconde fois le service :
docker start <mariadb>
docker exec <mariadb> mariadb-upgrade --user=root
docker restart <mariadb>mariadb-upgrade met à jour les tables système et vérifie les tables des autres bases. Petite subtilité utile pour vos scripts : avec --check-if-upgrade-is-needed, le code de sortie 0 signifie qu’une mise à niveau est nécessaire, et 1 qu’elle ne l’est pas.
Je n’ai relancé WordPress qu’après les contrôles suivants :
docker exec <mariadb> mariadb-upgrade \
--user=root --check-if-upgrade-is-needed
docker exec <mariadb> mariadb-check \
--user=root --all-databases --check --quick
docker exec <mariadb> mariadb-dump \
--user=root --all-databases --single-transaction --quick \
--routines --events --triggers > mariadb-after.sqlRésultat : version interne cohérente, tables système corrigées, contrôle global valide et dump complet à nouveau fonctionnel. J’ai enfin vérifié le blog depuis l’extérieur en IPv4 et en IPv6. Une base saine sans son application, ou une application visible sans sauvegarde restaurable, ne représente que la moitié du travail.
Empêcher Watchtower de refaire le coup
La correction durable se trouve dans la stack Compose. Pour MariaDB, j’utilise désormais une version validée associée à son empreinte immuable, et j’exclus explicitement le conteneur de Watchtower :
services:
db:
image: mariadb:12.3.2@sha256:<digest-vérifié>
environment:
MARIADB_AUTO_UPGRADE: "1"
labels:
com.centurylinklabs.watchtower.enable: "false"Un tag peut être réaffecté, alors qu’un digest Docker identifie un contenu précis. Le digest doit être récupéré et contrôlé au moment où vous validez votre version, pas copié aveuglément depuis cet article.
Le label d’exclusion est documenté dans la sélection des conteneurs Watchtower. Je l’ai doublé par une exclusion dans la configuration de Watchtower, mais une seule politique claire et contrôlée suffit normalement. MARIADB_AUTO_UPGRADE=1 reste une ceinture de sécurité pour une future évolution volontaire de l’image. Ce n’est pas une autorisation donnée à Watchtower pour appliquer seul toutes les versions majeures à venir.
Watchtower conserve donc son intérêt sur les conteneurs stateless dont le remplacement est réellement réversible. Pour MariaDB, il peut signaler qu’une mise à jour existe, mais la sauvegarde, la lecture des notes de version, la migration et la validation restent une opération de maintenance.
Une sauvegarde qui prouve quelque chose
Cette panne a aussi révélé une faiblesse dans mon script de sauvegarde. Il exportait les bases applicatives, mais pas toutes les bases, routines et événements (justement parceque Codex avait repéré ses erreurs lors de la mise à jour). Le dump quotidien inclut maintenant explicitement ces objets :
mariadb-dump --all-databases --single-transaction --quick \
--routines --events --triggers \
> <fichier-de-sauvegarde>Le script vérifie le code de sortie, la présence de la fin normale du dump et son intégration dans la sauvegarde finale. Le snapshot physique protège un instant avant une migration risquée. Le dump logique offre un format portable et contrôlable. Les deux sont complémentaires, mais aucun ne remplace un test de restauration.
Corriger un vieux conseil fait partie du jeu
Je pourrais discrètement modifier l’ancien article et faire comme si j’avais toujours déconseillé latest sur les bases de données. Ce serait pratique, mais pas très Geekeries.
Le conseil de 2020 répondait à un besoin réel : recevoir rapidement les correctifs sans administrer chaque conteneur à la main. Il était néanmoins trop général. Une application stateless, un reverse proxy et une base MariaDB avec plusieurs années d’état persistant n’ont ni le même risque ni la même procédure de retour arrière.
Automatiser la détection, oui. Automatiser le remplacement de toutes les bases de données, non.
Au final, aucune donnée WordPress n’a été perdue et le site n’a pas été cassé. Mais le dump en échec prouvait que la prochaine vraie urgence aurait pu être beaucoup moins amusante. Cette fois, le système a gagné une version figée, une migration reproductible, un rollback exploitable et une sauvegarde plus complète.
Bref, ne demandez pas seulement à votre conteneur s’il fonctionne. Demandez aussi à votre sauvegarde si elle saurait le reconstruire. Néanmoins maintenant il faudra faire ma newswatch cyber sur MariaDB, car les mises à jour ne se feront plus toute seule !
Geekez bien !

