Mettre à jour Dolibarr sous Docker sans perdre de migrations

Avec l'image Docker officielle, passer de la 20 à la 24 d'un coup laisse une base incomplète, sans aucune erreur. Ce qui se passe, comment le vérifier chez vous, et la bonne procédure, testée.

Versions concernées
Image officielle dolibarr/dolibarr, versions 16 à 24, avec MariaDB ou MySQL
Ce qui a été vérifié
Lecture du script de démarrage de l'image (docker-run.sh) et du script de migration de Dolibarr (install/upgrade.php). Test réel le 27/09/2026 : installation en 20.0.4, puis passage direct en 24.0.0 d'un côté, et version par version de l'autre, avec comptage des tables. Requête de contrôle testée sur des instances 16, 18, 20, 22 et 24. Dernières images relevées sur Docker Hub le 4/10/2026.

L’image Docker officielle dolibarr/dolibarr sait mettre à jour la base de données toute seule au démarrage. C’est pratique, et c’est pour cela qu’on a envie de changer le numéro de version dans docker-compose.yml, de relancer, et de passer à autre chose.

Si vous sautez plusieurs versions d’un coup, la base ne sera pas complète, et rien ne vous le dira. Nous l’avons vérifié le 27 septembre 2026 : une instance installée en 20.0.4, passée directement en 24.0.0 en suivant la documentation de l’image, se déclare en 24.0.0 et affiche « Migration successful ». Il lui manque pourtant 17 tables : 389 au lieu de 406 pour la même instance montée version par version. Les migrations des versions 22 et 23 n’ont jamais été jouées.

Pourquoi des migrations disparaissent

Au démarrage, le conteneur compare la version de la base à celle de ses fichiers. S’il y a un écart, il appelle le script de migration de Dolibarr une seule fois, de la version installée à la version cible. Or ce script ne retient que deux fichiers : celui qui part de votre version et celui qui arrive à la version visée. Pour un passage de la 20 à la 24, il joue la migration 2021 et la migration 2324. Tout ce qui se trouve entre les deux est ignoré.

L’assistant web de Dolibarr n’a pas ce défaut : il vous fait passer les étapes une par une. C’est l’enchaînement automatique de l’image qui pose problème.

L’application démarre normalement, on se connecte, les écrans principaux s’ouvrent. La panne n’apparaît que plus tard, le jour où l’on utilise une fonction qui dépend d’une table manquante : les catégories sur les factures ou les commandes, la comptabilité analytique, et d’autres. À ce moment-là, plus personne ne fait le lien avec la mise à jour.

Vérifier si votre base est complète

Cette requête cherche, pour chaque version de 17 à 24, un élément que seule la migration de cette version crée. Elle ne modifie rien. Lancez-la sur la base de Dolibarr :

SELECT m.version, m.objet AS manquant FROM (
  SELECT '17' AS version, 'llx_bank_extrafields' AS objet
  UNION ALL SELECT '18', 'llx_c_invoice_subtype'
  UNION ALL SELECT '20', 'llx_product_thirdparty'
  UNION ALL SELECT '21', 'llx_bank_import'
  UNION ALL SELECT '22', 'llx_categorie_invoice'
  UNION ALL SELECT '23', 'llx_accounting_analytic_axis'
  UNION ALL SELECT '24', 'llx_ai_request_log'
) m
WHERE m.objet NOT IN (
  SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE()
)
UNION ALL
SELECT '19', 'llx_c_tva.entity' FROM DUAL WHERE NOT EXISTS (
  SELECT 1 FROM information_schema.columns
  WHERE table_schema = DATABASE() AND table_name = 'llx_c_tva' AND column_name = 'entity'
)
ORDER BY 1;

Seules des versions supérieures à la vôtre doivent apparaître. Si vous êtes en 24 et que la requête renvoie une ligne, une migration a été sautée. Elle a été testée sur des instances 16, 18, 20, 22 et 24 installées normalement : chacune ne signale que les versions au-dessus d’elle.

La requête suppose le préfixe de tables par défaut, llx_. Si vous en utilisez un autre, adaptez les noms.

La bonne procédure

L’idée tient en une phrase : une version majeure à la fois, avec votre propre sauvegarde avant de commencer. Les noms de services ci-dessous (web, mariadb) sont ceux de l’exemple officiel ; adaptez-les aux vôtres.

  1. Sauvegardez vous-même. La base, et les deux dossiers persistants : documents et modules externes.

    docker compose exec -T mariadb sh -c 'mariadb-dump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' > sauvegarde-avant-maj.sql

    L’image fait bien une copie de la base avant chaque migration, mais elle porte toujours le même nom et elle est écrasée à l’étape suivante : après deux étapes, la copie de votre version de départ n’existe plus.

  2. Notez un numéro de version précis dans docker-compose.yml, jamais latest. Avec latest, un simple docker compose pull peut vous faire changer de version majeure sans que vous l’ayez décidé.

  3. Montez d’une seule version majeure : remplacez par exemple dolibarr/dolibarr:20.0.4 par dolibarr/dolibarr:21.0.4.

  4. Supprimez le verrou d’installation, sinon la base ne sera pas mise à jour et Dolibarr restera bloqué sur une page d’installation verrouillée :

    docker compose exec web rm -f /var/www/documents/install.lock
  5. Relancez et lisez le journal jusqu’à « Migration successful » :

    docker compose pull web && docker compose up -d && docker compose logs -f web
  6. Recommencez pour la version suivante, jusqu’à la version visée.

Les dernières images officielles de chaque branche, au 4 octobre 2026 : 16.0.5, 17.0.4, 18.0.9, 19.0.4, 20.0.4, 21.0.4, 22.0.5, 23.0.4 et 24.0.1. La 18.0.10 et la 24.0.2 existent, mais n’ont pas encore d’image. Avant de passer en 24, lisez le piège du journal inaltérable décrit dans Mettre à jour Dolibarr sans casse.

Avant chaque montée, le module gratuit Prêt pour la mise à jour fait la plupart des vérifications sans rien modifier : il lit le code de chaque module externe face à la version visée, contrôle PHP, la base de données, les champs calculés et les modèles ODT, puis vous remet un rapport. Il ne remplace ni la sauvegarde ni l’essai sur une copie.

Si une migration échoue

L’image restaure alors automatiquement la base telle qu’elle était, mais le conteneur, lui, reste sur les fichiers de la nouvelle version. Dolibarr se retrouve bloqué sur la page d’installation. Remettez le numéro de version précédent dans docker-compose.yml, relancez, puis lisez le fichier migration_error.html dans le dossier des documents pour comprendre ce qui a coincé.

Deux autres pièges de l’image

  • conf.php n’est pas conservé. Il se trouve dans le conteneur, pas dans un volume, et il est réécrit à partir des variables d’environnement à chaque recréation du conteneur, donc à chaque changement de version. Toute ligne ajoutée à la main disparaît. Passez vos réglages par les variables d’environnement, ou montez votre propre fichier.
  • La clé d’instance n’est pas aléatoire. La documentation de l’image dit que DOLI_INSTANCE_UNIQUE_ID est tirée au hasard à la création du conteneur. Dans le code, si la variable est vide, c’est la valeur fixe myinstanceuniquekey qui est écrite, la même pour tout le monde. Pour une nouvelle installation, fixez votre propre valeur dès le premier démarrage. Sur une instance existante, n’en changez pas : cette clé sert à chiffrer certains réglages enregistrés, qui deviendraient illisibles.

Si vous installez une nouvelle instance, deux autres défauts de l’image vous concernent (mots de passe enregistrés en MD5, tâches planifiées qui ne tournent jamais) : voir Installer Dolibarr avec Docker Compose.

Avec PostgreSQL, l’image ne fait aucune mise à jour automatique : il faut passer par l’assistant web, à l’adresse de votre Dolibarr suivie de /install/, là encore une version à la fois.

Si votre base a déjà sauté des versions

Ne relancez pas les migrations à la main sur l’instance réelle. La voie sûre consiste à repartir de la sauvegarde d’avant la mise à jour et à refaire la montée version par version. Sans sauvegarde, la base peut être complétée, mais c’est un travail à faire sur une copie, table par table, en vérifiant les données.

Le diagnostic à 90 € permet de savoir où en est votre base. Le forfait Mise à jour sécurisée répète toute la montée sur une copie de votre instance, sous Docker justement, avant de toucher à la vraie.

À lire aussi

DolibarrDockermise à jourdocker composeinstall.lockmigration