[UPDATE 2026] Migrer Odoo 17 en Docker : standalone (venv) → Docker Compose (4 instances) + 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}}(port8069) — instance de production principale{{INSTANCE_2}}(port8169) — instance de production secondairetest(port8269) — environnement de testadmin(port8369) — 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 → WEB → Add 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 :
|
1 |
nano /usr/local/vesta/data/templates/web/nginx/odoo-8069.tpl |
Contenu :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
server { listen %ip%:%proxy_port%; server_name %domain_idn% %alias_idn%; error_log /var/log/%web_system%/domains/%domain%.error.log error; location /.well-known/acme-challenge { default_type text/plain; root /home/%user%/web/%domain%/public_html; } location /longpolling { proxy_pass http://127.0.0.1:8072; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location / { proxy_pass http://127.0.0.1:8069; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location ~* /web/static/ { proxy_pass http://127.0.0.1:8069; proxy_cache_valid 200 90m; proxy_buffering on; expires 864000; } include %home%/%user%/conf/web/%domain%/nginx.conf_*; } |
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 :
|
1 |
nano /usr/local/vesta/data/templates/web/nginx/odoo-8069.stpl |
Contenu :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
server { listen %ip%:%proxy_ssl_port% ssl; http2 on; server_name %domain_idn% %alias_idn%; ssl_certificate %ssl_pem%; ssl_certificate_key %ssl_key%; error_log /var/log/%web_system%/domains/%domain%.error.log error; location /longpolling { proxy_pass http://127.0.0.1:8072; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location / { proxy_pass http://127.0.0.1:8069; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location ~* /web/static/ { proxy_pass http://127.0.0.1:8069; proxy_cache_valid 200 90m; proxy_buffering on; expires 864000; } include %home%/%user%/conf/web/%domain%/nginx.conf_*; } |
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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# Port 8169 ({{INSTANCE_2}}) sed 's/8069/8169/g; s/8072/8172/g' \ /usr/local/vesta/data/templates/web/nginx/odoo-8069.tpl \ > /usr/local/vesta/data/templates/web/nginx/odoo-8169.tpl sed 's/8069/8169/g; s/8072/8172/g' \ /usr/local/vesta/data/templates/web/nginx/odoo-8069.stpl \ > /usr/local/vesta/data/templates/web/nginx/odoo-8169.stpl # Port 8269 (test) sed 's/8069/8269/g; s/8072/8272/g' \ /usr/local/vesta/data/templates/web/nginx/odoo-8069.tpl \ > /usr/local/vesta/data/templates/web/nginx/odoo-8269.tpl sed 's/8069/8269/g; s/8072/8272/g' \ /usr/local/vesta/data/templates/web/nginx/odoo-8069.stpl \ > /usr/local/vesta/data/templates/web/nginx/odoo-8269.stpl # Port 8369 (admin) sed 's/8069/8369/g; s/8072/8372/g' \ /usr/local/vesta/data/templates/web/nginx/odoo-8069.tpl \ > /usr/local/vesta/data/templates/web/nginx/odoo-8369.tpl sed 's/8069/8369/g; s/8072/8372/g' \ /usr/local/vesta/data/templates/web/nginx/odoo-8069.stpl \ > /usr/local/vesta/data/templates/web/nginx/odoo-8369.stpl |
2.4 Appliquer les templates aux domaines
Appliquer chaque template au domaine correspondant avec la commande v-change-web-domain-proxy-tpl :
|
1 2 3 4 |
/usr/local/vesta/bin/v-change-web-domain-proxy-tpl {{USER_VESTA}} {{DOMAINE_ODOO_1}} odoo-8069 /usr/local/vesta/bin/v-change-web-domain-proxy-tpl {{USER_VESTA}} {{DOMAINE_ODOO_2}} odoo-8169 /usr/local/vesta/bin/v-change-web-domain-proxy-tpl {{USER_VESTA}} {{DOMAINE_ODOO_TEST}} odoo-8269 /usr/local/vesta/bin/v-change-web-domain-proxy-tpl {{USER_VESTA}} {{DOMAINE_ODOO_ADMIN}} odoo-8369 |
2.5 Vérifier et recharger Nginx
|
1 2 |
nginx -t systemctl reload 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 :
|
1 |
nginx: [warn] the "listen ... http2" directive is deprecated, use the "http2" directive instead |
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 :
|
1 2 |
listen %ip%:%proxy_ssl_port% ssl; http2 on; |
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 :
|
1 2 3 |
mkdir -p /home/docker/odoo17/config mkdir -p /home/docker/odoo17/ext_addons mkdir -p /home/docker/odoo17/backup |
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.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# Créer le répertoire des plugins Docker CLI mkdir -p /usr/local/lib/docker/cli-plugins # Télécharger Docker Compose v2 curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 \ -o /usr/local/lib/docker/cli-plugins/docker-compose # Rendre le binaire exécutable chmod +x /usr/local/lib/docker/cli-plugins/docker-compose # Vérifier l'installation docker compose version |
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 → Fichier → Gestionnaire de sites → Nouveau 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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Déplacer le docker-compose.yml sudo mv /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/docker-compose.yml \ /home/docker/odoo17/docker-compose.yml # Déplacer les fichiers de configuration Odoo sudo mv /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/odoo-{{INSTANCE_1}}.conf \ /home/docker/odoo17/config/odoo-{{INSTANCE_1}}.conf sudo mv /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/odoo-{{INSTANCE_2}}.conf \ /home/docker/odoo17/config/odoo-{{INSTANCE_2}}.conf sudo mv /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/odoo-test.conf \ /home/docker/odoo17/config/odoo-test.conf sudo mv /home/{{USER_VESTA}}/web/{{DOMAINE_ODOO_ADMIN}}/public_html/odoo-admin.conf \ /home/docker/odoo17/config/odoo-admin.conf |
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).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Propriétaire : root pour tout sudo chown -R root:root /home/docker/odoo17/ # docker-compose.yml : lecture root uniquement (contient des mots de passe) sudo chmod 600 /home/docker/odoo17/docker-compose.yml # Fichiers .conf : lisibles par tous (UID 101 dans le conteneur doit pouvoir les lire) sudo chmod 644 /home/docker/odoo17/config/*.conf # Répertoires : traversables sudo chmod 755 /home/docker/odoo17/ sudo chmod 755 /home/docker/odoo17/config/ sudo chmod -R 755 /home/docker/odoo17/ext_addons/ |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
version: '3.8' services: db: image: postgres:13 container_name: odoo17-db restart: always environment: POSTGRES_USER: odoo17 POSTGRES_PASSWORD: {{DB_PASSWORD}} POSTGRES_DB: postgres volumes: - odoo17-db-data:/var/lib/postgresql/data networks: - odoo17-network odoo-{{INSTANCE_1}}: image: odoo:17 container_name: odoo17-{{INSTANCE_1}} restart: always depends_on: - db ports: - "127.0.0.1:8069:8069" - "127.0.0.1:8072:8072" volumes: - odoo17-data:/var/lib/odoo - ./config/odoo-{{INSTANCE_1}}.conf:/etc/odoo/odoo.conf:ro - ./ext_addons:/mnt/extra-addons environment: - HOST=db - USER=odoo17 - PASSWORD={{DB_PASSWORD}} networks: - odoo17-network odoo-{{INSTANCE_2}}: image: odoo:17 container_name: odoo17-{{INSTANCE_2}} restart: always depends_on: - db ports: - "127.0.0.1:8169:8069" - "127.0.0.1:8172:8072" volumes: - odoo17-data:/var/lib/odoo - ./config/odoo-{{INSTANCE_2}}.conf:/etc/odoo/odoo.conf:ro - ./ext_addons:/mnt/extra-addons environment: - HOST=db - USER=odoo17 - PASSWORD={{DB_PASSWORD}} networks: - odoo17-network odoo-test: image: odoo:17 container_name: odoo17-test restart: always depends_on: - db ports: - "127.0.0.1:8269:8069" - "127.0.0.1:8272:8072" volumes: - odoo17-data:/var/lib/odoo - ./config/odoo-test.conf:/etc/odoo/odoo.conf:ro - ./ext_addons:/mnt/extra-addons environment: - HOST=db - USER=odoo17 - PASSWORD={{DB_PASSWORD}} networks: - odoo17-network odoo-admin: image: odoo:17 container_name: odoo17-admin restart: always depends_on: - db ports: - "127.0.0.1:8369:8069" - "127.0.0.1:8372:8072" volumes: - odoo17-data:/var/lib/odoo - ./config/odoo-admin.conf:/etc/odoo/odoo.conf:ro - ./ext_addons:/mnt/extra-addons environment: - HOST=db - USER=odoo17 - PASSWORD={{DB_PASSWORD}} networks: - odoo17-network volumes: odoo17-db-data: name: odoo17-db-data odoo17-data: name: odoo17-data networks: odoo17-network: name: odoo17-network |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[options] addons_path = /usr/lib/python3/dist-packages/odoo/addons,/mnt/extra-addons admin_passwd = {{ODOO_ADMIN_PASSWORD}} db_host = db db_port = 5432 db_user = odoo17 db_password = {{DB_PASSWORD}} dbfilter = ^{{INSTANCE_1}}$ http_port = 8069 longpolling_port = 8072 workers = 2 max_cron_threads = 1 limit_memory_hard = 2684354560 limit_memory_soft = 2147483648 limit_request = 8192 limit_time_cpu = 600 limit_time_real = 1200 server_wide_modules = base,web |
odoo-{{INSTANCE_2}}.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[options] addons_path = /usr/lib/python3/dist-packages/odoo/addons,/mnt/extra-addons admin_passwd = {{ODOO_ADMIN_PASSWORD}} db_host = db db_port = 5432 db_user = odoo17 db_password = {{DB_PASSWORD}} dbfilter = ^{{INSTANCE_2}}$ http_port = 8069 longpolling_port = 8072 workers = 2 max_cron_threads = 1 limit_memory_hard = 2684354560 limit_memory_soft = 2147483648 limit_request = 8192 limit_time_cpu = 600 limit_time_real = 1200 server_wide_modules = base,web |
odoo-test.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[options] addons_path = /usr/lib/python3/dist-packages/odoo/addons,/mnt/extra-addons admin_passwd = {{ODOO_ADMIN_PASSWORD}} db_host = db db_port = 5432 db_user = odoo17 db_password = {{DB_PASSWORD}} dbfilter = ^{{INSTANCE_1}}-test$ http_port = 8069 longpolling_port = 8072 workers = 1 max_cron_threads = 1 limit_memory_hard = 2684354560 limit_memory_soft = 2147483648 limit_request = 8192 limit_time_cpu = 600 limit_time_real = 1200 server_wide_modules = base,web |
odoo-admin.conf
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[options] addons_path = /usr/lib/python3/dist-packages/odoo/addons,/mnt/extra-addons admin_passwd = {{ODOO_ADMIN_PASSWORD}} db_host = db db_port = 5432 db_user = odoo17 db_password = {{DB_PASSWORD}} dbfilter = .* http_port = 8069 longpolling_port = 8072 workers = 1 max_cron_threads = 1 list_db = True limit_memory_hard = 2684354560 limit_memory_soft = 2147483648 limit_request = 8192 limit_time_cpu = 600 limit_time_real = 1200 server_wide_modules = base,web |
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.
|
1 2 3 4 |
# Sur l'ANCIEN serveur (en root ou avec sudo) sudo -u postgres pg_dump {{INSTANCE_1}} | gzip > /root/odoo17-db-{{INSTANCE_1}}.sql.gz sudo -u postgres pg_dump {{INSTANCE_2}} | gzip > /root/odoo17-db-{{INSTANCE_2}}.sql.gz sudo -u postgres pg_dump "{{DB_TEST_OLD_NAME}}" | gzip > /root/odoo17-db-test.sql.gz |
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.
|
1 2 3 4 5 6 |
# Trouver le répertoire filestore sudo find /home /root -type d -name filestore 2>/dev/null # Archiver le filestore (adapter le chemin trouvé ci-dessus) sudo tar -czf /root/odoo17-filestore.tar.gz \ -C /chemin/vers/.local/share/Odoo/ filestore/ |
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 :
|
1 2 3 4 5 |
cd /opt/odoo17/custom_addons/ tar -czf /root/odoo17-custom-addons.tar.gz \ module1/ \ module2/ \ ... |
6) Transférer les exports via rsync
Depuis le nouveau serveur, récupérer les archives créées sur l’ancien serveur :
|
1 2 3 4 5 6 7 8 9 10 |
# Depuis le NOUVEAU serveur rsync -avz -e "ssh -p {{PORT_SSH_ANCIEN}}" \ root@{{IP_ANCIEN}}:/root/odoo17-*.tar.gz \ /home/docker/odoo17/backup/ rsync -avz -e "ssh -p {{PORT_SSH_ANCIEN}}" \ root@{{IP_ANCIEN}}:/root/odoo17-db-{{INSTANCE_1}}.sql.gz \ root@{{IP_ANCIEN}}:/root/odoo17-db-{{INSTANCE_2}}.sql.gz \ root@{{IP_ANCIEN}}:/root/odoo17-db-test.sql.gz \ /home/docker/odoo17/backup/ |
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
|
1 2 |
cd /home/docker/odoo17/ tar -xzf backup/odoo17-custom-addons.tar.gz -C ext_addons/ |
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
|
1 2 |
cd /home/docker/odoo17/ docker compose up -d db |
Attendre que PostgreSQL soit prêt :
|
1 |
docker compose exec db pg_isready -U odoo17 |
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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Créer les bases vides docker compose exec db psql -U odoo17 -d postgres -c "CREATE DATABASE {{INSTANCE_1}};" docker compose exec db psql -U odoo17 -d postgres -c "CREATE DATABASE {{INSTANCE_2}};" docker compose exec db psql -U odoo17 -d postgres -c 'CREATE DATABASE "{{INSTANCE_1}}-test";' # Restaurer chaque base gunzip -c /home/docker/odoo17/backup/odoo17-db-{{INSTANCE_1}}.sql.gz | \ docker compose exec -T db psql -U odoo17 -d {{INSTANCE_1}} gunzip -c /home/docker/odoo17/backup/odoo17-db-{{INSTANCE_2}}.sql.gz | \ docker compose exec -T db psql -U odoo17 -d {{INSTANCE_2}} gunzip -c /home/docker/odoo17/backup/odoo17-db-test.sql.gz | \ docker compose exec -T db psql -U odoo17 -d {{INSTANCE_1}}-test |
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
|
1 |
docker compose exec db psql -U odoo17 -d postgres -c "\l" |
Tu devrais voir :
{{INSTANCE_1}}{{INSTANCE_2}}{{INSTANCE_1}}-testpostgres(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 :
|
1 |
docker volume create odoo17-data |
9.2 Extraire le filestore temporairement
|
1 |
tar -xzf /home/docker/odoo17/backup/odoo17-filestore.tar.gz -C /tmp/ |
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
|
1 |
docker volume inspect odoo17-data --format '{{ .Mountpoint }}' |
Exemple de sortie : /var/lib/docker/volumes/odoo17-data/_data
9.4 Copier le filestore dans le volume
|
1 2 |
mkdir -p /var/lib/docker/volumes/odoo17-data/_data/filestore/ cp -r /tmp/filestore/* /var/lib/docker/volumes/odoo17-data/_data/filestore/ |
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 :
|
1 |
chown -R 101:101 /var/lib/docker/volumes/odoo17-data/_data/filestore/ |
10) Démarrer toutes les instances Odoo
|
1 2 |
cd /home/docker/odoo17/ docker compose up -d |
Vérifier l’état des conteneurs :
|
1 |
docker compose ps |
Tous les conteneurs doivent être en état Up.
Consulter les logs en cas d’erreur :
|
1 2 3 4 |
docker compose logs odoo-{{INSTANCE_1}} docker compose logs odoo-{{INSTANCE_2}} docker compose logs odoo-test docker compose logs odoo-admin |
11) Tester localement (avant le DNS)
Depuis le serveur (en SSH), tester que chaque instance Odoo répond :
|
1 2 3 4 |
curl -I http://127.0.0.1:8069 curl -I http://127.0.0.1:8169 curl -I http://127.0.0.1:8269 curl -I http://127.0.0.1:8369 |
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 :
|
1 2 |
nslookup {{DOMAINE_ODOO_1}} dig +short {{DOMAINE_ODOO_1}} |
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 :
|
1 2 3 4 |
/usr/local/vesta/bin/v-add-letsencrypt-domain {{USER_VESTA}} {{DOMAINE_ODOO_1}} /usr/local/vesta/bin/v-add-letsencrypt-domain {{USER_VESTA}} {{DOMAINE_ODOO_2}} /usr/local/vesta/bin/v-add-letsencrypt-domain {{USER_VESTA}} {{DOMAINE_ODOO_TEST}} /usr/local/vesta/bin/v-add-letsencrypt-domain {{USER_VESTA}} {{DOMAINE_ODOO_ADMIN}} |
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
- Ouvrir FileZilla et se connecter au serveur (même connexion SFTP que dans la section 4.1)
- Naviguer vers
/home/docker/odoo17/ext_addons/(panneau de droite) - 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) :
|
1 2 |
cd /home/docker/odoo17/ docker compose restart odoo-{{INSTANCE_1}} |
Ou pour redémarrer toutes les instances :
|
1 |
docker compose restart |
É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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
MyVestaCP (proxy + SSL) Docker (application) ───────────────────────── ───────────────────── /home/{{USER_VESTA}}/web/ /home/docker/odoo17/ ├── {{DOMAINE_ODOO_1}}/ ├── docker-compose.yml │ └── Nginx → 127.0.0.1:8069 ├── config/ ├── {{DOMAINE_ODOO_2}}/ │ ├── odoo-{{INSTANCE_1}}.conf │ └── Nginx → 127.0.0.1:8169 │ ├── odoo-{{INSTANCE_2}}.conf ├── {{DOMAINE_ODOO_TEST}}/ │ ├── odoo-test.conf │ └── Nginx → 127.0.0.1:8269 │ └── odoo-admin.conf └── {{DOMAINE_ODOO_ADMIN}}/ ├── ext_addons/ └── Nginx → 127.0.0.1:8369 │ ├── module1/ │ ├── module2/ │ └── ... (autres modules) └── backup/ Docker Compose services: - odoo17-db (PostgreSQL 13, partagée) - odoo17-{{INSTANCE_1}} (port 8069/8072) - odoo17-{{INSTANCE_2}} (port 8169/8172) - odoo17-test (port 8269/8272) - odoo17-admin (port 8369/8372) |
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
0 commentaire