[UPDATE 2026] Akeneo PIM 6 vers 7 en Docker — migration, upgrade et centralisation serveur avec MyVestaCP
Akeneo PIM 6 → 7 en Docker — migration et upgrade
Sixième étape : migrer Akeneo PIM 6 (Community Edition) d’un VPS standalone
vers PIM 7 en Docker Compose sur le serveur centralisé, avec reverse proxy MyVestaCP.
Paramètres à adapter
Ce document utilise des variables entre {{...}}. Remplacez-les par vos propres valeurs avant d’exécuter les commandes.
| Variable | Description | Exemple |
|---|---|---|
{{HOSTNAME_VPS_PIM}} |
Hostname du VPS PIM (ancien) | vps-pim-ancien |
{{IP_VPS_PIM}} |
IP du VPS PIM | 203.0.113.50 |
{{USER_VPS_PIM}} |
Utilisateur SSH du VPS PIM | ubuntu |
{{HOSTNAME_NOUVEAU}} |
Hostname du nouveau serveur | vps-nouveau |
{{IP_NOUVEAU}} |
IP du nouveau serveur | 198.51.100.20 |
{{PORT_SSH_NOUVEAU}} |
Port SSH du nouveau serveur | 22 |
{{DOMAINE_PIM}} |
Domaine Akeneo PIM | pim.exemple.com |
{{MYSQL_ROOT_PASSWORD}} |
Mot de passe root MySQL | MonMotDePasseRoot! |
{{APP_SECRET}} |
Secret Symfony (APP_SECRET) | GenerateWithOpenSSLRand |
{{USER_VESTA}} |
Utilisateur VestaCP | admin |
Les identifiants MySQL akeneo_pim (user/db/password) sont les valeurs par défaut Akeneo. Changez le mot de passe en production.
Introduction
Akeneo PIM 6 (Community Edition, v6.0.45) tourne actuellement sur un VPS séparé
({{HOSTNAME_VPS_PIM}}, IP {{IP_VPS_PIM}}, SSH port 22, utilisateur SSH {{USER_VPS_PIM}}).
L’installation est en standalone : PHP 8.0, MySQL 8.0.30, Elasticsearch 7.x, le tout installé
directement sur le système dans /home/pim-community-standard/.
On migre vers le serveur centralisé ({{HOSTNAME_NOUVEAU}}, IP {{IP_NOUVEAU}},
SSH port {{PORT_SSH_NOUVEAU}}) en Docker Compose, avec un upgrade de PIM 6.0 vers PIM 7.0
en même temps.
Architecture cible
- 6 conteneurs Docker : MySQL 8.0.30, Elasticsearch 8.4.2, PHP 8.1 FPM, Nginx, Job Worker, Cron
- Domaine :
{{DOMAINE_PIM}}(port interne8480) - MyVestaCP gère le reverse proxy et les certificats SSL
- Fichiers Docker :
/home/docker/akeneo/
Ce qui change entre PIM 6 et PIM 7 :
PHP 8.0 → 8.1, Elasticsearch 7.x → 8.4.2,
le SKU n’est plus obligatoire (UUID devient l’identifiant technique),
les nouveaux endpoints API utilisent /products-uuid,
et la configuration du mailer passe en format DSN (MAILER_URL → MAILER_DSN).
Ressources nécessaires : Elasticsearch 8 consomme ~2-4 Go de RAM,
MySQL ~1-2 Go, PHP-FPM ~1 Go. Assurez-vous que la RAM disponible sur votre serveur est suffisant pour votre usage,
même en coexistence avec d’autres services.
1) Créer le domaine dans MyVestaCP
Dans le panel MyVestaCP → WEB → Add Web Domain :
{{DOMAINE_PIM}}
Paramètres :
- DNS Support : cocher (obligatoire pour Let’s Encrypt)
- Mail Support : décocher
- Advanced options : laisser les valeurs par défaut
DNS Support obligatoire : même si le DNS est géré ailleurs (OVH, Cloudflare, etc.),
il faut cocher DNS Support dans MyVestaCP. Le script v-add-letsencrypt-domain
a besoin de la zone DNS locale pour créer l’enregistrement _acme-challenge.
Sans cette zone, la demande de certificat échoue avec une erreur 404.
Important : ne pas activer Let’s Encrypt pour l’instant — le DNS ne pointe pas encore vers le nouveau serveur.
2) Créer les templates Nginx pour reverse proxy PIM
Même principe que pour Odoo : on crée des templates Nginx personnalisés pour que VestaCP
fasse du reverse proxy vers le conteneur Docker (port 8480).
2.1 Template HTTP : akeneo-8480.tpl
|
1 |
nano /usr/local/vesta/data/templates/web/nginx/akeneo-8480.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 |
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 / { proxy_pass http://127.0.0.1:8480; 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; client_max_body_size 128M; } include %home%/%user%/conf/web/%domain%/nginx.conf_*; } |
Le client_max_body_size 128M est important pour PIM : l’import de fichiers CSV
et l’upload d’images produits peuvent être volumineux.
2.2 Template HTTPS : akeneo-8480.stpl
|
1 |
nano /usr/local/vesta/data/templates/web/nginx/akeneo-8480.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 |
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 / { proxy_pass http://127.0.0.1:8480; 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 https; proxy_set_header X-Forwarded-Host $host; proxy_read_timeout 720s; proxy_connect_timeout 720s; proxy_send_timeout 720s; client_max_body_size 128M; } include %home%/%user%/conf/web/%domain%/nginx.conf_*; } |
2.3 Appliquer le template au domaine
|
1 |
/usr/local/vesta/bin/v-change-web-domain-proxy-tpl {{USER_VESTA}} {{DOMAINE_PIM}} akeneo-8480 |
2.4 Vérifier et recharger Nginx
|
1 2 |
nginx -t systemctl reload nginx |
3) Créer la structure des répertoires Docker
|
1 2 3 |
mkdir -p /home/docker/akeneo/pim mkdir -p /home/docker/akeneo/config/nginx mkdir -p /home/docker/akeneo/backup |
pim/: code source Akeneo PIM 7 (installé via Composer)config/nginx/: configuration Nginx pour le conteneur interneconfig/crontab: tâches planifiées PIM (créé en section 4.3)backup/: exports temporaires (dump MySQL, tar filestore)
4) Créer les fichiers de configuration Docker
4.1 Créer le docker-compose.yml
|
1 |
nano /home/docker/akeneo/docker-compose.yml |
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 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 |
services: mysql: image: mysql:8.0.30 container_name: akeneo-mysql restart: always environment: MYSQL_ROOT_PASSWORD: {{MYSQL_ROOT_PASSWORD}} MYSQL_DATABASE: akeneo_pim MYSQL_USER: akeneo_pim MYSQL_PASSWORD: akeneo_pim volumes: - akeneo-mysql-data:/var/lib/mysql command: ['--default-authentication-plugin=mysql_native_password', '--log-bin-trust-function-creators=1'] networks: - akeneo-network elasticsearch: image: elastic/elasticsearch:8.4.2 container_name: akeneo-es restart: always environment: ES_JAVA_OPTS: '-Xms512m -Xmx512m' discovery.type: single-node xpack.security.enabled: 'false' xpack.security.http.ssl.enabled: 'false' volumes: - akeneo-es-data:/usr/share/elasticsearch/data networks: - akeneo-network php: image: akeneo/pim-php-dev:8.1 container_name: akeneo-php restart: always user: "0:0" volumes: - ./pim:/srv/pim working_dir: /srv/pim depends_on: - mysql - elasticsearch environment: APP_ENV: prod XDEBUG_MODE: 'off' PHP_MEMORY_LIMIT: 1024M networks: - akeneo-network nginx: image: nginx:1.25-alpine container_name: akeneo-nginx restart: always ports: - "127.0.0.1:8480:80" volumes: - ./pim/public:/srv/pim/public:ro - ./config/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - php networks: - akeneo-network job-worker: image: akeneo/pim-php-dev:8.1 container_name: akeneo-job restart: always user: www-data volumes: - ./pim:/srv/pim working_dir: /srv/pim command: ['php', 'bin/console', 'messenger:consume', 'ui_job', 'import_export_job', 'data_maintenance_job', 'scheduled_job', '--time-limit=300', '--memory-limit=1024M'] depends_on: - php - mysql - elasticsearch environment: APP_ENV: prod XDEBUG_MODE: 'off' networks: - akeneo-network cron: image: docker:27-cli container_name: akeneo-cron restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./config/crontab:/crontab:ro entrypoint: ["/bin/sh", "-c", "cp /crontab /var/spool/cron/crontabs/root && chmod 0600 /var/spool/cron/crontabs/root && crond -f"] depends_on: - php volumes: akeneo-mysql-data: name: akeneo-mysql-data akeneo-es-data: name: akeneo-es-data networks: akeneo-network: name: akeneo-network |
Points clés :
mysql:8.0.30avecmysql_native_password(Akeneo ne supporte pas le nouveau plugin d’authentification MySQL 8) etlog_bin_trust_function_creators=1(nécessaire pour les migrations qui créent des triggers)elastic/elasticsearch:8.4.2en mode single-node, sécurité désactivée (réseau Docker interne)akeneo/pim-php-dev:8.1pour PHP-FPM avec toutes les extensions requises. Leuser: "0:0"fait tourner le conteneur en root pour éviter les erreurs de permission sur les logs PHP-FPM et le cache Symfonynginx:1.25-alpinecomme serveur web interne, exposé sur le port8480- job-worker : démon qui traite les imports/exports et tâches asynchrones via 4 queues PIM 7 (
ui_job,import_export_job,data_maintenance_job,scheduled_job). Le--time-limit=300le redémarre toutes les 5 minutes (libère la mémoire) - cron : conteneur léger (
docker:27-cli, ~15 Mo) qui exécute les tâches planifiées PIM viadocker execdans le conteneur PHP. Tout est dans le compose, pas de crontab à configurer sur l’hôte - Réseau et volumes complètement séparés d’Odoo
Image akeneo/pim-php-dev:8.1 : c’est l’image officielle Akeneo pour le développement.
Elle inclut toutes les extensions PHP requises (apcu, bcmath, imagick, intl, etc.). Pour la production,
Akeneo ne fournit pas d’image officielle. On désactive Xdebug via XDEBUG_MODE=off.
user: "0:0" sur le service php : sans cela, le conteneur tourne en www-data
et PHP-FPM ne peut pas écrire son fichier de log (Permission denied: /var/log/php8.1-fpm.log),
ce qui provoque un crash en boucle de supervisord. Le job-worker garde user: www-data
car il n’a pas besoin d’accès root (il exécute uniquement des commandes Symfony).
Queues PIM 7 : PIM 6 utilisait une seule queue (main_queue).
PIM 7 la remplace par 4 queues spécialisées : ui_job, import_export_job,
data_maintenance_job, scheduled_job. Si vous gardez main_queue,
le job-worker crashe avec No such transport "main_queue".
Conteneur cron et Docker socket : le service cron monte le
docker.sock en lecture seule pour pouvoir exécuter docker exec
dans le conteneur PHP. C’est le même mécanisme que la crontab hôte, mais conteneurisé.
Les commandes PIM tournent dans le contexte du conteneur akeneo-php
(mêmes volumes, même réseau, mêmes variables d’environnement).
Avantage : un docker compose down && up -d restaure tout automatiquement,
pas de crontab à reconfigurer manuellement.
4.2 Créer la configuration Nginx interne
|
1 |
nano /home/docker/akeneo/config/nginx/default.conf |
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 |
server { listen 80; server_name _; root /srv/pim/public; client_max_body_size 128M; location / { try_files $uri /index.php$is_args$args; } location ~ ^/index\.php(/|$) { fastcgi_pass php:9000; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_read_timeout 600; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; internal; } location ~ \.php$ { return 404; } } |
Ce Nginx interne (dans Docker) proxie les requêtes PHP vers le conteneur php (FPM port 9000).
Le Nginx de MyVestaCP (sur l’hôte) proxie vers ce Nginx interne sur le port 8480.
C’est une architecture classique « double reverse proxy ».
4.3 Créer le fichier crontab
|
1 |
nano /home/docker/akeneo/config/crontab |
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 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# Akeneo PIM 7 - Crons conteneurisés (documentation officielle CE) # Les commandes s'exécutent dans le conteneur akeneo-php via docker exec # Source : https://docs.akeneo.com/7.0/install_pim/manual/installation_ce.html # === DATA QUALITY INSIGHTS (DQI) === # Planifier les tâches DQI périodiques (tous les jours à 00:15) 15 0 * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:data-quality-insights:schedule-periodic-tasks --env=prod 2>&1 # Préparer les évaluations DQI (toutes les 10 minutes) */10 * * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:data-quality-insights:prepare-evaluations --env=prod 2>&1 # Exécuter les évaluations DQI (toutes les 30 minutes) */30 * * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:data-quality-insights:evaluations --env=prod 2>&1 # Nettoyer les résultats de complétude DQI (tous les jours à 00:30) 30 0 * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:data-quality-insights:clean-completeness-evaluation-results --no-interaction --env=prod 2>&1 # === VERSIONING === # Rafraîchir les versions (tous les jours à 03:00) 0 3 * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:versioning:refresh --env=prod 2>&1 # Purger les anciennes versions (dimanche à 01:00) 0 1 * * 0 docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:versioning:purge --more-than-days 90 --no-interaction --force --env=prod 2>&1 # === MAINTENANCE === # Purger les anciens jobs (1er du mois à minuit) 0 0 1 * * docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:batch:purge-job-execution --env=prod 2>&1 # Agréger les volumes (tous les jours à 04:00) 0 4 * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:volume:aggregate --env=prod 2>&1 # Pousser les jobs planifiés dans la queue (toutes les 10 minutes) */10 * * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console pim:job-automation:push-scheduled-jobs-to-queue --env=prod 2>&1 # Purger les messages Doctrine (toutes les 2 heures) 0 */2 * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:messenger:doctrine:purge-messages messenger_messages default --env=prod 2>&1 # === CONNECTIVITY === # Audit de connectivité (toutes les heures à :01) 1 * * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:connectivity-audit:update-data --env=prod 2>&1 # Purger les erreurs de connexion (toutes les heures à :10) 10 * * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:connectivity-connection:purge-error --env=prod 2>&1 # Purger le compteur d'erreurs d'audit (tous les jours à 12:40) 40 12 * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:connectivity-audit:purge-error-count --env=prod 2>&1 # Purger les logs Events API (toutes les heures à :05) 5 * * * * docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:connectivity-connection:purge-events-api-logs --env=prod 2>&1 # Rotation des clés OpenID (dimanche à 21:04) 4 21 * * 0 docker exec -u www-data akeneo-php php /srv/pim/bin/console akeneo:connectivity-connection:openid-keys:create --no-interaction --env=prod 2>&1 |
Ligne vide obligatoire à la fin : BusyBox crond (utilisé par Alpine)
exige une ligne vide à la fin du fichier crontab. Sans elle, la dernière entrée est ignorée
silencieusement.
15 crons officiels CE : ces crons sont regroupés en 4 catégories :
Data Quality Insights (4 crons — calcul des scores qualité),
Versioning (2 crons — historique des modifications),
Maintenance (4 crons — purge, volumes, jobs planifiés, messages),
Connectivity (5 crons — audit, purge erreurs, logs API, clés OpenID).
Source : documentation officielle PIM 7.0 CE.
Modifier les crons : pour ajouter ou supprimer un cron, éditer le fichier
/home/docker/akeneo/config/crontab puis redémarrer le conteneur :
docker compose restart cron.
5) Installer le code PIM 7 via Composer
On utilise l’image Docker PHP pour télécharger et installer PIM 7 sans rien installer sur l’hôte.
|
1 2 3 4 5 6 7 8 |
# Installer PIM 7 Community Edition via Composer # On monte le PARENT (/home/docker/akeneo) et on laisse Composer créer le sous-répertoire pim docker run -ti --rm \ -v /home/docker/akeneo:/srv/akeneo \ -w /srv/akeneo \ akeneo/pim-php-dev:8.1 \ php /usr/local/bin/composer create-project \ akeneo/pim-community-standard /srv/akeneo/pim "7.0.*@stable" |
Point de montage : ne pas monter directement /home/docker/akeneo/pim
comme volume — Composer a besoin de créer le répertoire cible lui-même.
On monte donc le répertoire parent et on laisse create-project
créer le sous-répertoire pim. La commande tourne en root
(pas -u www-data) pour éviter les erreurs de permission.
5.0.1 Corriger les permissions après installation
|
1 2 |
# Remettre la propriété à www-data (UID 33) pour les conteneurs PHP/Nginx chown -R 33:33 /home/docker/akeneo/pim |
5.0.2 Créer le fichier docker/supervisord.conf
L’image akeneo/pim-php-dev:8.1 utilise supervisord comme processus principal,
mais pim-community-standard installé via Composer n’inclut pas le fichier de configuration.
Sans ce fichier, le conteneur PHP crashe en boucle avec Error: could not find config file docker/supervisord.conf.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
mkdir -p /home/docker/akeneo/pim/docker cat > /home/docker/akeneo/pim/docker/supervisord.conf << 'EOF' [supervisord] nodaemon=true user=root logfile=/dev/null logfile_maxbytes=0 [program:php-fpm] command=/usr/local/sbin/php-fpm -F autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 EOF chown -R 33:33 /home/docker/akeneo/pim/docker/ |
user=root et -F sont obligatoires :
sans user=root, supervisord affiche un warning CRIT running as root, privileges were not dropped.
Sans -F (foreground), PHP-FPM se détache en arrière-plan (daemonize) : le processus parent
quitte avec status 0, supervisord croit qu’il a crashé et tente de le relancer, mais le port 9000
est toujours occupé par le processus enfant orphelin — résultat : crash en boucle avec
Address already in use (98).
Première exécution longue : Composer télécharge toutes les dépendances (~500 Mo).
Cette commande peut prendre 5-10 minutes selon la connexion.
Si elle échoue sur un timeout, relancer avec COMPOSER_PROCESS_TIMEOUT=600.
5.1 Créer le fichier .env.local
Ce fichier contient la configuration spécifique à notre environnement Docker.
Il surcharge les valeurs par défaut de .env.
|
1 |
nano /home/docker/akeneo/pim/.env.local |
Contenu :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
APP_ENV=prod APP_SECRET={{APP_SECRET}} APP_DATABASE_HOST=mysql APP_DATABASE_PORT=3306 APP_DATABASE_NAME=akeneo_pim APP_DATABASE_USER=akeneo_pim APP_DATABASE_PASSWORD=akeneo_pim APP_INDEX_HOSTS=elasticsearch:9200 APP_PRODUCT_AND_PRODUCT_MODEL_INDEX_NAME=akeneo_pim_product_and_product_model APP_CONNECTION_ERROR_INDEX_NAME=akeneo_connectivity_connection_error APP_EVENTS_API_DEBUG_INDEX_NAME=akeneo_connectivity_connection_events_api_debug APP_ELASTICSEARCH_TOTAL_FIELDS_LIMIT=10000 AKENEO_PIM_URL=https://{{DOMAINE_PIM}} MAILER_URL=null://localhost APP_DEFAULT_LOCALE=en APP_DEBUG=0 XDEBUG_MODE=off |
Différences avec PIM 6 :
APP_DATABASE_HOST pointe vers mysql (nom du service Docker, pas localhost).
APP_INDEX_HOSTS pointe vers elasticsearch:9200.
AKENEO_PIM_URL utilise https:// (après activation Let’s Encrypt).
5.2 Permissions
|
1 2 3 4 5 6 7 8 9 10 |
# Le code PIM doit appartenir à www-data (UID 33) sudo chown -R 33:33 /home/docker/akeneo/pim/ # docker-compose.yml : lecture root uniquement sudo chmod 600 /home/docker/akeneo/docker-compose.yml # Répertoires Docker : traversables sudo chmod 755 /home/docker/akeneo/ sudo chmod 755 /home/docker/akeneo/config/ sudo chmod 755 /home/docker/akeneo/config/nginx/ |
6) Préparer la base PIM 6 avant l’export
Avant d’exporter la base, il faut s’assurer que toutes les migrations PIM 6
ont été appliquées. On fait cela sur le VPS PIM 6.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Sur le VPS PIM (root@{{HOSTNAME_VPS_PIM}}) cd /home/pim-community-standard/ # Copier les fichiers de migration cp -R ./vendor/akeneo/pim-community-dev/upgrades/* ./upgrades/ # Vider le cache (en tant que root) rm -rf var/cache/* # Appliquer toutes les migrations PIM 6 en attente sudo -u www-data php bin/console doctrine:migrations:migrate --no-interaction # Reconstruire le cache (obligatoire après le nettoyage) sudo -u www-data php bin/console cache:clear --env=prod sudo -u www-data php bin/console cache:warmup --env=prod |
Permissions : le rm -rf var/cache/* doit être fait en root,
mais les commandes cache:clear et cache:warmup doivent être lancées
en tant que www-data (via sudo -u www-data), sinon le cache sera recréé
avec des permissions root et PIM 6 retournera une erreur 500 Internal Server Error au prochain redémarrage.
Si cela arrive, corriger avec : chown -R www-data:www-data /home/pim-community-standard/var/
Si doctrine:migrations:migrate affiche No migrations to execute,
c’est normal — cela signifie que la base PIM 6 est déjà à jour.
7) Exporter les données depuis le VPS PIM 6
Sur le VPS PIM ({{IP_VPS_PIM}}), on exporte la base MySQL et le filestore.
7.1 Arrêter les workers PIM 6
|
1 2 3 4 5 |
# Sur le VPS PIM ({{USER_VPS_PIM}}@{{HOSTNAME_VPS_PIM}}) # Arrêter les démons de queue pour éviter les modifications pendant l'export sudo supervisorctl stop all 2>/dev/null # Ou si pas de supervisord, trouver et arrêter les process PHP daemon ps aux | grep "messenger:consume\|job-queue" | grep -v grep |
7.2 Exporter la base MySQL
|
1 2 |
# Sur le VPS PIM mysqldump -u akeneo_pim -pakeneo_pim akeneo_pim | gzip > /home/{{USER_VPS_PIM}}/akeneo-pim-db.sql.gz |
La base se nomme akeneo_pim, utilisateur akeneo_pim,
mot de passe akeneo_pim (tel que configuré dans le .env de PIM 6).
7.3 Exporter le filestore
|
1 2 3 |
# Sur le VPS PIM cd /home/pim-community-standard/ tar -czf /home/{{USER_VPS_PIM}}/akeneo-pim-filestore.tar.gz var/file_storage/ |
7.4 Exporter le cache média (optionnel)
|
1 2 3 |
# Le cache média sera régénéré automatiquement, mais pour éviter d'attendre : cd /home/pim-community-standard/ tar -czf /home/{{USER_VPS_PIM}}/akeneo-pim-media.tar.gz public/media/ 2>/dev/null |
8) Transférer les exports via rsync
Depuis le nouveau serveur ({{IP_NOUVEAU}}), récupérer les archives :
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# Depuis le NOUVEAU serveur rsync -avz -e "ssh" \ {{USER_VPS_PIM}}@{{IP_VPS_PIM}}:/home/{{USER_VPS_PIM}}/akeneo-pim-db.sql.gz \ /home/docker/akeneo/backup/ rsync -avz -e "ssh" \ {{USER_VPS_PIM}}@{{IP_VPS_PIM}}:/home/{{USER_VPS_PIM}}/akeneo-pim-filestore.tar.gz \ /home/docker/akeneo/backup/ rsync -avz -e "ssh" \ {{USER_VPS_PIM}}@{{IP_VPS_PIM}}:/home/{{USER_VPS_PIM}}/akeneo-pim-media.tar.gz \ /home/docker/akeneo/backup/ 2>/dev/null |
Le VPS PIM utilise le port SSH par défaut (22), donc pas besoin de -p.
Si une clé SSH n’est pas configurée, utiliser scp à la place.
9) Démarrer les services et restaurer la base
9.1 Démarrer MySQL et Elasticsearch
|
1 2 |
cd /home/docker/akeneo/ docker compose up -d mysql elasticsearch |
Ne pas démarrer tous les services : à cette étape, ne lancer que
mysql et elasticsearch. Le conteneur PHP sera démarré après
la restauration de la base et la correction des permissions (sections 9.2 et 10).
Attendre que MySQL soit prêt :
|
1 2 |
# Attendre ~15 secondes puis vérifier docker compose exec mysql mysqladmin ping -u akeneo_pim -pakeneo_pim |
Quand tu vois mysqld is alive, c’est prêt.
Vérifier Elasticsearch :
|
1 |
docker compose exec elasticsearch curl -s http://localhost:9200/_cluster/health | python3 -m json.tool |
Le status doit être green ou yellow.
9.2 Supprimer la base vide et restaurer le dump PIM 6
|
1 2 3 4 5 6 7 |
# Supprimer la base créée automatiquement par Docker docker compose exec mysql mysql -u root -p{{MYSQL_ROOT_PASSWORD}} \ -e "DROP DATABASE akeneo_pim; CREATE DATABASE akeneo_pim DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # Restaurer le dump PIM 6 gunzip -c /home/docker/akeneo/backup/akeneo-pim-db.sql.gz | \ docker compose exec -T mysql mysql -u akeneo_pim -pakeneo_pim akeneo_pim |
Attention : la restauration peut prendre plusieurs minutes selon la taille de la base.
Ne pas interrompre le processus.
9.3 Restaurer le filestore
|
1 2 3 4 5 6 7 8 9 10 11 |
# Extraire le filestore dans le répertoire PIM tar -xzf /home/docker/akeneo/backup/akeneo-pim-filestore.tar.gz \ -C /home/docker/akeneo/pim/ # Restaurer le cache média (si exporté) tar -xzf /home/docker/akeneo/backup/akeneo-pim-media.tar.gz \ -C /home/docker/akeneo/pim/ 2>/dev/null # Corriger les permissions sudo chown -R 33:33 /home/docker/akeneo/pim/var/ sudo chown -R 33:33 /home/docker/akeneo/pim/public/media/ 2>/dev/null |
10) Exécuter la migration PIM 6.0 → 7.0
Maintenant que la base PIM 6 est restaurée dans le conteneur MySQL et que le code PIM 7
est installé, on peut exécuter les migrations Doctrine pour upgrader le schéma.
10.0.1 Corriger les permissions du cache
Le code PIM a été installé en root (section 5), donc le répertoire var/
appartient à root. Il faut corriger les permissions depuis l’intérieur du conteneur
pour que www-data puisse créer le cache.
|
1 2 |
# Créer et corriger les permissions du cache (depuis l'intérieur du conteneur) docker compose exec -u root php bash -c "mkdir -p /srv/pim/var/cache/prod /srv/pim/var/log && chown -R www-data:www-data /srv/pim/var/" |
Important : la commande chown doit être faite depuis l’intérieur
du conteneur (via docker compose exec), pas depuis l’hôte. Le chown
depuis l’hôte avec chown -R 33:33 peut ne pas fonctionner correctement selon le type
de volume Docker utilisé.
10.1 Démarrer le conteneur PHP
|
1 2 |
cd /home/docker/akeneo/ docker compose up -d php |
10.2 Vider le cache
|
1 |
docker compose exec -u www-data php rm -rf var/cache/ |
10.3 Créer les index Elasticsearch (obligatoire avant les migrations)
Les migrations Doctrine incluent une étape de conversion UUID qui a besoin des index Elasticsearch.
Si les index n’existent pas, la migration échouera avec index_not_found_exception
sur akeneo_pim_product_and_product_model.
|
1 |
docker compose exec -u www-data php php bin/console akeneo:elasticsearch:reset-indexes --no-interaction |
10.4 Exécuter les migrations Doctrine
|
1 |
docker compose exec -u www-data php php bin/console doctrine:migrations:migrate --no-interaction |
Migration très longue (1 à 3 heures) : cette commande applique toutes les migrations de schéma
entre PIM 5.0 et PIM 7.0 (les versions 5.0 → 6.0 sont incluses dans le code PIM 7).
Les étapes les plus longues sont :
ALTER TABLE pim_versioning_version— cette table stocke l’historique complet
de chaque modification de chaque entité PIM. C’est la plus grosse table de la base (souvent > 1 Go).
L’ALTER TABLE crée une copie temporaire, ce qui peut prendre 1 à 2 heures.- Conversion UUID (
Version_7_0_20220429131804_execute_uuid_migration) —
crée des triggers temporaires sur plusieurs tables pour migrer les identifiants vers des UUID. - INSERT INTO
pim_data_quality_insights_*—
peuple les tables de scoring qualité, plusieurs milliers de lignes par table.
Monitoring : pour vérifier que la migration progresse, ouvrir un second terminal et observer le processlist MySQL :
docker compose exec mysql mysql -u akeneo_pim -pakeneo_pim akeneo_pim -e "SHOW FULL PROCESSLIST;".
Un Time qui augmente sur un ALTER TABLE est normal.
Des warnings did not result in any SQL statements sont bénins.
10.5 Migrations de données complémentaires
|
1 2 3 |
# Mettre à jour les scores de qualité des données docker compose exec -u www-data php php bin/console \ pim:data-quality-insights:populate-product-models-scores-and-ki |
11) Réindexer Elasticsearch et compiler les assets
11.1 Réindexer Elasticsearch
|
1 2 3 4 5 6 7 8 |
# Réinitialiser les index (PIM 7 utilise ES 8.4.2, structure différente) docker compose exec -u www-data php php bin/console akeneo:elasticsearch:reset-indexes # Réindexer tous les produits docker compose exec -u www-data php php bin/console pim:product:index --all # Réindexer les modèles de produits docker compose exec -u www-data php php bin/console pim:product-model:index --all |
La réindexation peut prendre du temps si tu as beaucoup de produits.
C’est normal — Elasticsearch reconstruit tout l’index depuis MySQL.
11.2 Préparer les fichiers requis par webpack
Webpack a besoin de fichiers générés par Symfony (routes JS, require-paths, bundles publics).
Ces commandes doivent être exécutées depuis le conteneur PHP avant de lancer Node.
|
1 2 3 4 5 6 7 8 9 10 11 |
# Créer les répertoires nécessaires docker compose exec -u root php bash -c "mkdir -p /srv/pim/public/js && chown www-data:www-data /srv/pim/public/js" # Générer require-paths.js docker compose exec -u www-data php php bin/console pim:installer:dump-require-paths # Générer les routes JavaScript docker compose exec -u www-data php php bin/console fos:js-routing:dump --format=json --target=public/js/fos_js_routes.json # Installer les assets des bundles Symfony (copie, pas symlink) docker compose exec -u root php php bin/console assets:install public |
assets:install sans --symlink : utiliser la copie (pas les liens symboliques).
Avec --symlink, webpack suit les symlinks vers vendor/ et ne trouve plus
les modules @akeneo-pim-community/* dans node_modules/.
La commande assets:install doit tourner en root pour pouvoir créer
les répertoires dans public/bundles/.
11.3 Compiler les assets frontend
La compilation se fait avec un conteneur node:18 éphémère.
L’ordre des commandes est important : packages:build (compile les front-packages
TypeScript en JavaScript), puis less, puis webpack.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 1. Installer les dépendances et builder les workspace packages docker run -ti --rm -u root \ -v /home/docker/akeneo/pim:/srv/pim \ -w /srv/pim \ node:18 yarn install # 2. Compiler les front-packages TypeScript (génère lib/index.js) docker run -ti --rm -u root \ -v /home/docker/akeneo/pim:/srv/pim \ -w /srv/pim \ node:18 yarn run packages:build # 3. Compiler les feuilles de style LESS docker run -ti --rm -u root \ -v /home/docker/akeneo/pim:/srv/pim \ -w /srv/pim \ node:18 yarn run less # 4. Compiler le bundle JavaScript final docker run -ti --rm -u root \ -v /home/docker/akeneo/pim:/srv/pim \ -w /srv/pim \ node:18 yarn run webpack |
packages:build obligatoire : sans cette étape, webpack échoue avec 333 erreurs
Module not found: Can't resolve '@akeneo-pim-community/shared'.
Les front-packages sont en TypeScript source (src/) et leur package.json
déclare "main": "./lib/index.js". Le répertoire lib/ n’existe qu’après
la compilation par packages:build (qui lance tsc sur chaque workspace).
Compilation longue : le build complet (install + packages + less + webpack)
prend environ 5-10 minutes et consomme beaucoup de RAM.
C’est une opération unique (pas besoin de le refaire à chaque redémarrage).
Les commandes tournent en -u root pour éviter les erreurs de permission
sur node_modules/.
11.4 Générer extensions.json
Le frontend PIM charge /js/extensions.json au démarrage pour connaître la liste
des extensions de formulaires (menus, onglets, champs, etc.). Sans ce fichier, le dashboard
reste bloqué sur « Loading… » à l’infini après la connexion.
Ce fichier est généré par un script Node (pas par une commande Symfony) qui lit
require-paths.js (généré en 11.2), scanne les fichiers form_extensions.yml
de chaque bundle, et les fusionne en un seul JSON.
|
1 2 3 4 5 |
# Générer extensions.json (obligatoire pour que le frontend fonctionne) docker run -ti --rm -u root \ -v /home/docker/akeneo/pim:/srv/pim \ -w /srv/pim \ node:18 node vendor/akeneo/pim-community-dev/frontend/build/update-extensions.js |
Fichier critique : aucune commande bin/console ne génère ce fichier.
Il n’est référencé dans aucune documentation officielle Akeneo pour les installations self-hosted.
Si /js/extensions.json retourne 404, le PIM se connecte mais affiche un écran
« Loading… » infini avec l’animation du dinosaure.
11.5 Corriger les permissions après compilation
|
1 2 |
# Les assets ont été créés en root, remettre www-data pour PHP/Nginx chown -R 33:33 /home/docker/akeneo/pim/public/ |
11.6 Vider le cache Symfony
|
1 |
docker compose exec -u www-data php php bin/console cache:clear --env=prod |
12) Démarrer tous les services
|
1 2 |
cd /home/docker/akeneo/ docker compose up -d |
Vérifier l’état de tous les conteneurs :
|
1 |
docker compose ps |
Les 6 conteneurs doivent être en état Up :
akeneo-mysqlakeneo-esakeneo-phpakeneo-nginxakeneo-jobakeneo-cron
Consulter les logs en cas d’erreur :
|
1 2 3 |
docker compose logs php docker compose logs nginx docker compose logs job-worker |
13) Tester localement (avant le DNS)
|
1 |
curl -I http://127.0.0.1:8480 |
La commande doit retourner HTTP/1.1 302 Found avec un header Location
pointant vers /user/login. Cela confirme que PIM 7 fonctionne.
Identifiants par défaut PIM : admin / admin.
Si tu as changé le mot de passe dans PIM 6, les anciens identifiants sont conservés après la migration.
14) Basculer les enregistrements DNS
Créer (ou modifier) l’enregistrement A chez le registrar :
| Sous-domaine | Type | Cible |
|---|---|---|
{{DOMAINE_PIM}} |
A | {{IP_NOUVEAU}} |
Vérifier la propagation :
|
1 2 |
nslookup {{DOMAINE_PIM}} dig +short {{DOMAINE_PIM}} |
15) Activer Let’s Encrypt
|
1 |
/usr/local/vesta/bin/v-add-letsencrypt-domain {{USER_VESTA}} {{DOMAINE_PIM}} |
Important : attendre que le DNS pointe vers {{IP_NOUVEAU}} avant de lancer
cette commande. Let’s Encrypt valide via HTTP.
16) Vérifier les crons PIM
Les crons PIM sont déjà configurés dans le docker-compose.yml (section 4.1)
via le conteneur akeneo-cron et le fichier config/crontab (section 4.3).
Ils démarrent automatiquement avec docker compose up -d.
Vérifier que le conteneur cron tourne :
|
1 2 |
docker compose ps cron docker compose logs cron |
Pour vérifier qu’un cron s’est bien exécuté, consulter les logs du conteneur PHP
(les commandes docker exec y redirigent leur sortie) :
|
1 |
docker compose logs --tail=20 php |
Avantage par rapport au crontab hôte : tout est dans le compose.
Un docker compose down && up -d restaure les crons automatiquement.
Si tu migres le serveur à nouveau, pas de crontab à reconfigurer manuellement.
Récapitulatif de l’architecture finale
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
MyVestaCP (proxy + SSL) Docker (application) ——————————————— —————————— /home/{{USER_VESTA}}/web/ /home/docker/akeneo/ └── {{DOMAINE_PIM}}/ ├── docker-compose.yml └── Nginx → 127.0.0.1:8480 ├── pim/ (code PIM 7) ├── config/nginx/ (vhost interne) ├── config/crontab (tâches planifiées) └── backup/ Docker Compose services (6 conteneurs) : - akeneo-mysql (MySQL 8.0.30) - akeneo-es (Elasticsearch 8.4.2) - akeneo-php (PHP 8.1 FPM) - akeneo-nginx (Nginx 1.25) - akeneo-job (Job Worker / Queue Consumer) - akeneo-cron (Crons PIM via docker exec) |
Coexistence sur le serveur : Akeneo PIM, Odoo 8 et Odoo 17 tournent sur le même
serveur, complètement isolés dans leurs réseaux Docker respectifs :
akeneo-network: MySQL 8.0.30 + ES 8.4.2 + PHP + Nginx + Job Worker + Cron (port 8480)odoo17-network: PostgreSQL 13 + Odoo 17 (ports 8069/8169/8269/8369)odoo8-network: PostgreSQL 9.6 + Odoo 8 (ports 8469/8472)
En cas de problème
Erreur 502 Bad Gateway
Le conteneur PHP-FPM n’est pas prêt ou a crashé :
|
1 2 |
docker compose logs php docker compose restart php nginx |
Erreur « Connection refused » sur Elasticsearch
Elasticsearch n’a pas démarré (souvent un problème de mémoire ou de vm.max_map_count) :
|
1 2 3 4 5 6 7 |
# Vérifier les logs docker compose logs elasticsearch # Si erreur max_map_count, exécuter sur l'hôte : sudo sysctl -w vm.max_map_count=262144 # Et pour le rendre permanent : echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf |
Erreur de permission sur le filestore
|
1 2 3 |
sudo chown -R 33:33 /home/docker/akeneo/pim/var/ sudo chown -R 33:33 /home/docker/akeneo/pim/public/media/ docker compose restart php |
Écran « Loading… » infini après la connexion
Le fichier extensions.json est manquant. Vérifier :
|
1 |
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8480/js/extensions.json |
Si le résultat est 404, regénérer le fichier (section 11.4) :
|
1 2 3 4 5 |
docker run -ti --rm -u root \ -v /home/docker/akeneo/pim:/srv/pim \ -w /srv/pim \ node:18 node vendor/akeneo/pim-community-dev/frontend/build/update-extensions.js chown 33:33 /home/docker/akeneo/pim/public/js/extensions.json |
PHP-FPM crash en boucle avec « Address already in use (98) »
Vérifier que supervisord.conf contient bien command=/usr/local/sbin/php-fpm -F
(avec le flag -F pour le mode foreground). Sans ce flag, PHP-FPM se détache et
supervisord tente de le relancer en boucle (voir section 5.0.2).
Job-worker crash avec « No such transport « main_queue » »
PIM 7 a remplacé main_queue par 4 queues séparées.
Vérifier le command du service job-worker dans docker-compose.yml
(voir section 4.1).
À suivre
Akeneo PIM 7 est maintenant opérationnel en Docker avec reverse proxy et SSL.
Dans les prochains articles :
- ownCloud — migration des données et Docker Compose
- Serveurs de jeux — CS 1.6, TeamSpeak 3, EmuLinker
- Sauvegardes — stratégie et automatisation
0 commentaire