[UPDATE 2026] Migrer Odoo 17 en Docker : standalone (venv) → Docker Compose (4 instances) + reverse proxy MyVestaCP

Published by David on






Odoo 17 en Docker — migration standalone vers Docker Compose avec reverse proxy MyVestaCP

Odoo 17 en Docker — migration standalone vers Docker Compose

Quatrième étape : migrer Odoo 17 d’une installation standalone (venv Python 3.12 + PostgreSQL 13) vers Docker Compose avec 4 instances et reverse proxy MyVestaCP.

Document paramétrable

Ce guide utilise des variables {{...}} à remplacer par vos propres valeurs.
Vous pouvez aussi donner ce document à une IA avec vos paramètres pour générer une version personnalisée.

Variable Description Exemple
{{IP_ANCIEN}} IP de l’ancien serveur 203.0.113.10
{{IP_NOUVEAU}} IP du nouveau serveur 198.51.100.20
{{HOSTNAME_ANCIEN}} Hostname de l’ancien serveur vps-ancien
{{HOSTNAME_NOUVEAU}} Hostname du nouveau serveur vps-nouveau
{{PORT_SSH_ANCIEN}} Port SSH de l’ancien serveur 22
{{PORT_SSH_NOUVEAU}} Port SSH du nouveau serveur 22
{{DOMAINE_ODOO_1}} Sous-domaine de l’instance prod principale odoo-prod.exemple.com
{{DOMAINE_ODOO_2}} Sous-domaine de l’instance prod secondaire odoo-client2.exemple.com
{{DOMAINE_ODOO_TEST}} Sous-domaine de l’instance test odoo-test.exemple.com
{{DOMAINE_ODOO_ADMIN}} Sous-domaine de l’instance admin odoo-admin.exemple.com
{{ALIAS_ODOO_1}} Alias du domaine principal (optionnel) erp.mondomaine.com
{{INSTANCE_1}} Nom de l’instance/BDD prod principale prod
{{INSTANCE_2}} Nom de l’instance/BDD prod secondaire client2
{{DB_PASSWORD}} Mot de passe PostgreSQL MotDePassePostgres
{{ODOO_ADMIN_PASSWORD}} Mot de passe admin (master password) Odoo MotDePasseOdooAdmin
{{DB_TEST_OLD_NAME}} Ancien nom de la BDD de test (sur l’ancien serveur) prod-20260101-test
{{USER_VESTA}} Utilisateur VestaCP admin

Note : les noms d’instances ({{INSTANCE_1}}, {{INSTANCE_2}})
sont utilisés comme noms de base de données, noms de conteneurs Docker et dans les dbfilter.
Choisissez des noms courts, sans espaces ni caractères spéciaux.

Introduction

Sur l’ancien serveur ({{HOSTNAME_ANCIEN}}, IP {{IP_ANCIEN}}, SSH port {{PORT_SSH_ANCIEN}}),
Odoo 17 fonctionne en installation standalone : un environnement virtuel Python 3.12 et PostgreSQL 13 installés directement sur le système.

Sur le nouveau serveur ({{HOSTNAME_NOUVEAU}}, IP {{IP_NOUVEAU}}, SSH port {{PORT_SSH_NOUVEAU}}),
nous migrons vers une architecture Docker Compose avec 4 instances Odoo 17 partageant une seule base de données PostgreSQL 13.

Architecture cible

  • 4 instances Odoo 17 :
    • {{INSTANCE_1}} (port 8069) — instance de production principale
    • {{INSTANCE_2}} (port 8169) — instance de production secondaire
    • test (port 8269) — environnement de test
    • admin (port 8369) — interface d’administration
  • 1 conteneur PostgreSQL 13 partagé entre toutes les instances
  • MyVestaCP gère le reverse proxy Nginx et les certificats SSL (Let’s Encrypt)
  • Fichiers Docker : /home/docker/odoo17/

Avantages de cette architecture :
isolation des instances (une mise à jour de module n’affecte pas les autres),
multi-tenant (plusieurs bases de données, plusieurs clients),
facilité de déploiement (backup, scale, rollback via Docker),
et SSL/proxy géré par VestaCP (pas besoin de Traefik ou reverse proxy custom).

1) Créer les domaines dans MyVestaCP

Chaque instance Odoo nécessite un domaine (ou sous-domaine) distinct.
On crée les 4 domaines dans le panel MyVestaCP avant de configurer le proxy.

1.1 Créer les domaines

Dans le panel MyVestaCP → WEBAdd Web Domain :

  • {{DOMAINE_ODOO_1}}
  • {{DOMAINE_ODOO_2}}
  • {{DOMAINE_ODOO_TEST}}
  • {{DOMAINE_ODOO_ADMIN}}

Pour chaque domaine :

  • DNS Support : décocher (le DNS est géré ailleurs, par exemple OVH)
  • Mail Support : décocher (Odoo n’a pas besoin de serveur mail ici)
  • Advanced options : laisser les valeurs par défaut

1.2 Ajouter un alias au domaine principal

Le domaine {{DOMAINE_ODOO_1}} a un alias {{ALIAS_ODOO_1}}.
Dans le panel → éditer le domaine → champ Aliases : ajouter {{ALIAS_ODOO_1}}.

Important : ne pas activer Let’s Encrypt pour l’instant — le DNS ne pointe pas encore vers le nouveau serveur.
On activera SSL après avoir basculé les enregistrements DNS (section 12).

2) Créer les templates Nginx pour reverse proxy Odoo

Par défaut, MyVestaCP sert les fichiers statiques depuis /home/{{USER_VESTA}}/web/domaine/public_html/.
Pour Odoo, on veut qu’il proxy les requêtes vers les conteneurs Docker (ports 8069, 8169, 8269, 8369).

La solution : créer des templates Nginx personnalisés qui indiquent à VestaCP de faire du reverse proxy
au lieu de servir des fichiers. On aura besoin de deux templates par port :

  • odoo-XXXX.tpl (HTTP, port 80)
  • odoo-XXXX.stpl (HTTPS, port 443)

2.1 Template HTTP : odoo-8069.tpl

Créer le fichier /usr/local/vesta/data/templates/web/nginx/odoo-8069.tpl :

Contenu :

Le location /.well-known/acme-challenge est nécessaire pour que Let’s Encrypt puisse valider le domaine
avant d’émettre un certificat SSL (challenge HTTP-01).

2.2 Template HTTPS : odoo-8069.stpl

Créer le fichier /usr/local/vesta/data/templates/web/nginx/odoo-8069.stpl :

Contenu :

Important : utiliser listen %ip%:%proxy_ssl_port% ssl; suivi de http2 on; sur deux lignes distinctes.
La syntaxe listen ... ssl http2 (sur une seule ligne) est dépréciée dans Nginx 1.25+ et génère un warning.

On ne met pas les directives ssl_stapling dans le template initial — elles causent des warnings
avec les certificats auto-signés. VestaCP les ajoutera automatiquement lors de l’activation de Let’s Encrypt.

2.3 Dupliquer les templates pour les autres ports

On duplique les templates pour les ports 8169, 8269 et 8369 en utilisant sed :

2.4 Appliquer les templates aux domaines

Appliquer chaque template au domaine correspondant avec la commande v-change-web-domain-proxy-tpl :

2.5 Vérifier et recharger Nginx

Si nginx -t affiche syntax is ok et test is successful, la configuration est correcte.

2bis) Troubleshooting : warnings Nginx courants

Warning : listen ... http2 deprecated

Si tu vois ce warning lors du nginx -t :

C’est que le template utilise l’ancienne syntaxe listen ... ssl http2 sur une seule ligne.
Modifier le template pour séparer http2 sur sa propre ligne :

Warning : ssl_stapling ignored, issuer certificate not found

Avant l’activation de Let’s Encrypt, le serveur utilise un certificat auto-signé.
OCSP stapling ne peut pas fonctionner avec un certificat auto-signé, d’où le warning.
Ce warning disparaîtra automatiquement après l’activation de Let’s Encrypt (section 13).

Si tu veux éviter ce warning avant Let’s Encrypt, retire les lignes ssl_stapling on; et ssl_stapling_verify on;
du template .stpl. Elles seront automatiquement ajoutées par VestaCP lors de l’activation de Let’s Encrypt.

3) Créer la structure des répertoires Docker

On crée une structure de dossiers pour organiser la configuration Odoo, les modules personnalisés et les backups :

  • config/ : fichiers de configuration Odoo (odoo-{{INSTANCE_1}}.conf, etc.)
  • ext_addons/ : modules personnalisés (account-reconcile, prestashop_connector_basic, etc.)
  • backup/ : exports temporaires (dumps SQL, tar filestore)

3.1 Installer Docker Compose v2 (plugin)

Le paquet docker.io des dépôts Debian n’inclut pas le plugin Docker Compose v2.
La commande docker compose (avec espace) ne fonctionnera pas sans l’installer manuellement.

Attention : apt install docker-compose-plugin ne fonctionne pas
car ce paquet n’existe que dans le dépôt officiel Docker (docker.com), pas dans les dépôts Debian.
On installe donc le binaire manuellement.

Tu devrais voir quelque chose comme Docker Compose version v2.x.x.
Toutes les commandes docker compose de ce guide utilisent la syntaxe v2 (avec espace, sans tiret).

Docker Compose v1 (docker-compose avec tiret) est déprécié depuis juillet 2023.
Si l’ancien docker-compose est installé sur le serveur, il n’est pas nécessaire de le désinstaller — les deux coexistent sans conflit.

4) Uploader les fichiers de configuration

On uploade les fichiers de configuration sur le serveur via le FTP de MyVestaCP
(le domaine {{DOMAINE_ODOO_ADMIN}} a déjà été créé dans le panel),
puis on les déplace vers /home/docker/odoo17/ via SSH.

Pourquoi pas SFTP ? Si le serveur a le 2FA (TOTP) activé,
FileZilla ne peut pas gérer l’authentification multi-facteur (clé SSH + code TOTP).
Le FTP de VestaCP contourne ce problème. Alternative : utiliser WinSCP,
qui supporte nativement le 2FA.

4.1 Upload via le FTP VestaCP

Ouvrir FileZilla → FichierGestionnaire de sitesNouveau site :

  • Protocole : FTP - File Transfer Protocol
  • Hôte : {{DOMAINE_ODOO_ADMIN}} (ou l’IP du serveur)
  • Port : 21 (par défaut)
  • Type d’authentification : Normale
  • Utilisateur : l’utilisateur FTP du domaine (créé par VestaCP, ex : {{USER_VESTA}})
  • Mot de passe : le mot de passe FTP du panel

Uploader les 5 fichiers suivants à la racine (/public_html/) :

Fichier local Destination finale
docker-compose.yml /home/docker/odoo17/docker-compose.yml
odoo-{{INSTANCE_1}}.conf /home/docker/odoo17/config/odoo-{{INSTANCE_1}}.conf
odoo-{{INSTANCE_2}}.conf /home/docker/odoo17/config/odoo-{{INSTANCE_2}}.conf
odoo-test.conf /home/docker/odoo17/config/odoo-test.conf
odoo-admin.conf /home/docker/odoo17/config/odoo-admin.conf

4.2 Déplacer les fichiers via SSH

Les fichiers uploadés par FTP atterrissent dans /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/.
On les déplace vers leur emplacement final :

4.3 Permissions

Le docker-compose.yml contient des mots de passe — on restreint sa lecture à root.
Les fichiers .conf doivent rester lisibles par le conteneur Odoo (UID 101).

Le FTP de VestaCP pourra être réutilisé à l’avenir pour uploader de nouveaux modules Odoo.
Uploader dans /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/,
puis déplacer vers /home/docker/odoo17/ext_addons/ via SSH
(voir section « Future : ajouter un module Odoo »).

4.4 Contenu du docker-compose.yml

Les ports sont bindés sur 127.0.0.1 (localhost uniquement) — seul Nginx (reverse proxy) peut y accéder.
Les instances ne sont pas exposées directement sur Internet, ce qui améliore la sécurité.

4.5 Contenu des fichiers de configuration Odoo

odoo-{{INSTANCE_1}}.conf

odoo-{{INSTANCE_2}}.conf

odoo-test.conf

odoo-admin.conf

Le paramètre dbfilter contrôle quelle(s) base(s) de données l’instance peut voir :
^{{INSTANCE_1}}$ = uniquement la base « {{INSTANCE_1}} »,
.* = toutes les bases (mode admin).
Cela permet d’isoler les instances : un utilisateur sur {{DOMAINE_ODOO_1}}
ne verra jamais la base « {{INSTANCE_2}} » ni les autres.

5) Exporter les données depuis l’ancien serveur

Sur l’ancien serveur, on exporte :

  • Les bases de données Odoo (uniquement celles nécessaires, pas tout le serveur)
  • Le filestore (fichiers uploadés dans Odoo : images, PDF, pièces jointes)
  • Les modules personnalisés (addons custom)

5.1 Export des bases de données

On exporte uniquement les bases Odoo nécessaires avec pg_dump (une par base).

Ne pas utiliser pg_dumpall : il exporte toutes les bases et tous les rôles du serveur
(y compris ceux d’autres applications comme ownCloud, etc.), ce qui crée des bases et rôles parasites
dans le conteneur Docker. Le rôle odoo17 est déjà créé automatiquement par Docker Compose
(POSTGRES_USER), donc pas besoin d’exporter les rôles.

Les bases à exporter sont celles qui correspondent aux dbfilter des instances Odoo.
Ici : {{INSTANCE_1}} (production), {{INSTANCE_2}} (production secondaire),
et {{DB_TEST_OLD_NAME}} (test, sera renommée en {{INSTANCE_1}}-test).

5.2 Export du filestore

Le filestore Odoo contient tous les fichiers uploadés (images produits, factures PDF, pièces jointes).
Il se trouve dans ~/.local/share/Odoo/filestore/ de l’utilisateur qui exécute Odoo.

On utilise /root/ au lieu de /tmp/ car ce dernier peut avoir
des restrictions d’écriture sur certains serveurs (permissions, mount flags).

5.3 Export des modules personnalisés

Archiver les modules custom installés sur l’ancien serveur.
Exemple avec plusieurs dossiers de modules :

6) Transférer les exports via rsync

Depuis le nouveau serveur, récupérer les archives créées sur l’ancien serveur :

Si la connexion SSH échoue, vérifier que la clé SSH a bien été configurée (voir article précédent, section 1.1).

7) Extraire les modules personnalisés

Les modules sont maintenant dans /home/docker/odoo17/ext_addons/.
Ils seront montés dans les conteneurs via docker-compose.yml (volume ./ext_addons:/mnt/extra-addons).

8) Démarrer PostgreSQL et restaurer les bases de données

8.1 Démarrer le conteneur PostgreSQL

Attendre que PostgreSQL soit prêt :

Quand tu vois ... accepting connections, c’est prêt.

8.2 Restaurer les bases de données

Pas besoin de restaurer les rôles PostgreSQL : le rôle odoo17 est déjà créé
automatiquement par Docker Compose via POSTGRES_USER: odoo17.

On crée d’abord les bases vides, puis on restaure chaque dump :

La base de test est exportée sous le nom {{DB_TEST_OLD_NAME}} sur l’ancien serveur,
mais on la restaure directement dans {{INSTANCE_1}}-test sur le nouveau serveur
(pour correspondre au dbfilter de l’instance test). Pas besoin de renommer après coup.

8.4 Vérifier les bases de données

Tu devrais voir :

  • {{INSTANCE_1}}
  • {{INSTANCE_2}}
  • {{INSTANCE_1}}-test
  • postgres (base système)

9) Restaurer le filestore

Le filestore doit être copié dans le volume Docker odoo17-data,
qui est monté sur /var/lib/odoo dans les conteneurs Odoo.

9.1 Créer le volume Docker

Le volume odoo17-data est défini dans docker-compose.yml mais n’est créé
que lorsqu’un conteneur Odoo démarre. Comme seul le conteneur db tourne à ce stade,
il faut créer le volume manuellement :

9.2 Extraire le filestore temporairement

Le dossier /tmp/filestore/ contient maintenant un sous-dossier par base de données (ex : /tmp/filestore/{{INSTANCE_1}}/).

9.3 Trouver le mountpoint du volume

Exemple de sortie : /var/lib/docker/volumes/odoo17-data/_data

9.4 Copier le filestore dans le volume

9.5 Corriger les permissions

Le conteneur Odoo s’exécute avec l’utilisateur UID 101 (utilisateur odoo dans le conteneur).
Il faut que les fichiers du filestore appartiennent à cet utilisateur :

10) Démarrer toutes les instances Odoo

Vérifier l’état des conteneurs :

Tous les conteneurs doivent être en état Up.

Consulter les logs en cas d’erreur :

11) Tester localement (avant le DNS)

Depuis le serveur (en SSH), tester que chaque instance Odoo répond :

Chaque commande doit retourner HTTP/1.0 303 SEE OTHER (redirection vers /web).

À ce stade, les instances Odoo fonctionnent en local sur le serveur.
Elles ne sont pas encore accessibles depuis Internet tant que le DNS n’a pas été basculé.

12) Basculer les enregistrements DNS

Maintenant que tout fonctionne en local, on bascule les enregistrements A des domaines
pour qu’ils pointent vers le nouveau serveur.

Enregistrements DNS à mettre à jour

Chez ton registrar (OVH, Gandi, Cloudflare, etc.) ou dans la zone DNS du domaine :

Sous-domaine Type Cible
{{DOMAINE_ODOO_1}} A {{IP_NOUVEAU}}
{{DOMAINE_ODOO_2}} A {{IP_NOUVEAU}}
{{DOMAINE_ODOO_TEST}} A {{IP_NOUVEAU}}
{{DOMAINE_ODOO_ADMIN}} A {{IP_NOUVEAU}}
{{ALIAS_ODOO_1}} A {{IP_NOUVEAU}}

La propagation DNS prend généralement quelques minutes (si le TTL est faible, ex : 300 secondes),
mais peut aller jusqu’à 24 heures selon les FAI et les serveurs DNS récursifs.

Vérifier la propagation depuis ton PC :

Quand tu vois {{IP_NOUVEAU}}, le DNS a basculé.

13) Activer Let’s Encrypt (certificats SSL)

Une fois le DNS propagé, demander les certificats SSL pour chaque domaine :

Important : attendre que le DNS pointe bien vers le nouveau serveur avant de lancer ces commandes.
Let’s Encrypt valide le domaine via HTTP (challenge /.well-known/acme-challenge/).
Si le DNS pointe encore vers l’ancien serveur, la validation échouera.

MyVestaCP renouvelle automatiquement les certificats via un cron quotidien.
Pas besoin de configurer Certbot manuellement.

Future : Ajouter un nouveau module Odoo

Pour installer un nouveau module Odoo personnalisé (téléchargé depuis GitHub, Odoo Apps Store, ou développé en interne) :

Étape 1 : Uploader le module via FileZilla

  1. Ouvrir FileZilla et se connecter au serveur (même connexion SFTP que dans la section 4.1)
  2. Naviguer vers /home/docker/odoo17/ext_addons/ (panneau de droite)
  3. Glisser-déposer le dossier du module depuis ton PC (panneau de gauche)

Exemple : tu uploades my_custom_module/, qui contient __manifest__.py, models/, views/, etc.

Étape 2 : Redémarrer l’instance Odoo

Depuis le serveur (SSH) :

Ou pour redémarrer toutes les instances :

Étape 3 : Activer le mode développeur dans Odoo

Se connecter à l’instance Odoo → Paramètres → tout en bas → Activer le mode développeur.

Étape 4 : Mettre à jour la liste des applications

Applications → menu hamburger (trois points) → Mettre à jour la liste des applications.

Étape 5 : Installer le module

Chercher le nom du module dans la liste → cliquer sur Installer.

Grâce au volume ./ext_addons:/mnt/extra-addons dans docker-compose.yml,
tous les modules uploadés dans /home/docker/odoo17/ext_addons/ sont immédiatement disponibles
dans toutes les instances Odoo ({{INSTANCE_1}}, {{INSTANCE_2}}, test, admin).

Récapitulatif de l’architecture finale

Voici l’architecture complète après migration :

Points clés de cette architecture :

  • Séparation des responsabilités : MyVestaCP gère le proxy et le SSL, Docker gère l’application
  • Isolation : chaque instance Odoo a sa propre configuration (dbfilter, workers)
  • Sécurité : les ports Odoo sont bindés sur 127.0.0.1 (pas d’accès direct depuis Internet)
  • Scalabilité : facile d’ajouter une 5ème instance en dupliquant un service dans docker-compose.yml
  • Maintenance : les modules custom sont centralisés dans ext_addons/ et partagés par toutes les instances

À suivre

Odoo 17 est maintenant opérationnel en Docker avec reverse proxy et SSL.
Dans les prochains articles :

  • Odoo 8 en Docker — migration séparée (Python 2.7, PostgreSQL 9.6, ancien format de modules)
  • Akeneo PIM — gestion centralisée des produits (Docker, MySQL, Elasticsearch)
  • ownCloud — migration des données et Docker Compose
  • Serveurs de jeux — CS 1.6, TeamSpeak 3, EmuLinker
  • Sauvegardes — stratégie et automatisation

Article précédent : Migration des sites web — WordPress, PrestaShop, sites statiques.



Catégories : Non classé

0 commentaire

Laisser un commentaire

Emplacement de l’avatar

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *