DDEV Composer : exécuter et configurer Composer dans les conteneurs

Exécuter Composer dans DDEV sans polluer l’hôte : cache persistant, COMPOSER_HOME, tokens sécurisés, gestion des permissions, diagnostics et bonnes pratiques CI/CD.

Trois écrans affichent des commandes Composer avec un clavier en avant-plan.

Table des matières :

  1. DDEV Composer : périmètre, versions et intérêt réel des conteneurs
  2. Exécuter Composer dans DDEV : ddev composer vs ddev exec, et implications permissions
  3. Configurer Composer dans les conteneurs : cache, COMPOSER_HOME, tokens et secrets
  4. PrestaShop : où Composer apporte quelque chose (et où il ne faut pas fantasmer)
  5. Erreurs fréquentes avec DDEV Composer (et fixes reproductibles)
  6. DDEV Composer + CI/CD : aligner local, build reproductible et audit de dépendances

DDEV Composer : périmètre, versions et intérêt réel des conteneurs

Le sujet ici n’est pas “comment installer Composer”, mais comment exécuter et configurer Composer dans les conteneurs DDEV de manière reproductible, sans polluer l’hôte, et sans se retrouver avec un vendor/ incohérent à cause d’une version de PHP ou d’extensions différentes. Les exemples ci-dessous sont validés sur un socle courant en 2026 : DDEV 1.24.x, Docker Engine 26.x, PrestaShop 9.1.x (Symfony 6.4) avec PHP 8.3, et une variante PrestaShop 8.2.x avec PHP 8.2. Si vous ciblez encore PrestaShop 1.7 ou PHP 7.4, vous allez cumuler les contournements (et DDEV n’est pas le problème).

Composer est explicitement fait pour gérer des dépendances en fonction d’une plateforme PHP donnée (version + extensions). La doc officielle pose le cadre sans détour :

“Composer is a dependency manager for PHP.” — Documentation Composer, getcomposer.org

Dans un projet PrestaShop moderne (8/9), Composer sert à la fois pour l’écosystème Symfony, les outils dev (PHPStan, Rector, PHPUnit, etc.) et parfois des libs applicatives dans des modules. Exécuter Composer dans le conteneur web DDEV vous garantit que la résolution de dépendances voit la même plateforme que celle qui exécute réellement le code (PHP, ext-intl, ext-gd, ext-zip, ext-sodium, etc.). C’est le moyen le plus simple d’éviter les “ça marche sur ma machine” qui viennent… littéralement de “ma machine”.

Deux implications pratiques (souvent sous-estimées) :

  • Même “plateforme” que la prod/CI : si votre DDEV tourne en PHP 8.3 mais que votre CI/serveur reste en 8.2, vous devez le décider explicitement (voir section “mismatch de plateforme”). Sinon, Composer peut introduire des packages qui passent en local mais cassent ailleurs.
  • Même jeu d’extensions : c’est fréquemment l’extension manquante (intl, zip, gd, sodium…) qui explique un composer install impossible sur une machine, alors qu’il passe sur une autre. En conteneur, vous standardisez ce point.

Enfin, dans un contexte d’équipe (par exemple une équipe répartie entre Windows/macOS et Linux, ou entre plusieurs sites/agences), le gain est très concret : vous réduisez drastiquement les divergences de runtime et les variations de performance liées aux environnements locaux.

Exécuter Composer dans DDEV : ddev composer vs ddev exec, et implications permissions

DDEV expose généralement Composer de deux façons : via un wrapper dédié (ddev composer …) ou via un shell/exec dans le conteneur (ddev exec composer …). Le wrapper est pratique car il cible le bon conteneur et le bon répertoire de travail (le docroot monté dans /var/www/html). Dans 90% des cas, vous voulez simplement faire :

# Dans la racine du projet (là où se trouve composer.json)
ddev start

ddev composer install
# ou
ddev composer update

L’alternative “brute” est utile dès que vous devez chaîner des commandes, vérifier l’environnement, ou exécuter Composer dans un sous-dossier (typiquement un module) :

ddev exec -- pwd
# /var/www/html

ddev exec -- composer --version

ddev exec -- bash -lc 'cd modules/monmodule && composer install'

Pour décider rapidement, gardez ce mémo en tête :

Besoin Commande recommandée Pourquoi
Installer/mettre à jour à la racine du projet ddev composer install / ddev composer update Wrapper simple, contexte correct par défaut
Exécuter Composer dans un sous-dossier (ex. module) ddev exec -- bash -lc 'cd … && composer …' Vous contrôlez le cd, les variables, le shell
Déboguer une erreur de plateforme/extension ddev exec -- php -v + ddev exec -- php -m Vérification directe du runtime effectif
Diagnostiquer Composer ddev exec -- composer diagnose Rapport utile (config, réseau, TLS, etc.)

Point qui casse des projets : les permissions. Sur macOS/Windows (montages de volumes), sur Linux (UID/GID) ou avec des fichiers créés en root, vous pouvez vous retrouver avec un vendor/ non modifiable par votre user. DDEV exécute normalement les commandes en tant qu’un utilisateur non-root dans le conteneur (souvent ddev). Évitez sudo composer … dans le conteneur, évitez docker exec -u root … “pour dépanner”, parce que vous allez surtout créer des fichiers que votre IDE ou Git ne pourra plus gérer proprement.

Si vous suspectez un problème de droits, voici un check minimal, reproductible, avant de “tout casser” :

ddev exec -- bash -lc 'whoami && id && ls -ld vendor || true'
  • Si vendor/ appartient à root (ou à un UID inattendu), supprimez-le puis réinstallez proprement dans le conteneur.
  • Évitez de “réparer” avec un chmod -R 777 : ça masque le problème et peut créer d’autres comportements indésirables.

Pour comprendre vos outils DDEV côté CLI (shell, exec, ssh, extensions d’images), l’article existant est un bon rappel opérationnel : DDEV : outils développeur intégrés, ddev exec/ssh et extensions d’image.

Configurer Composer dans les conteneurs : cache, COMPOSER_HOME, tokens et secrets

Sans configuration, Composer retélécharge beaucoup et vous perdez du temps à chaque install/update, surtout sur des projets PrestaShop chargés (plusieurs centaines de packages + plugins). En local, le cache change la donne : un premier composer install peut prendre 1–3 minutes selon le réseau et le FS, tandis qu’un second run avec cache chaud retombe fréquemment sous 30–60 secondes (ordre de grandeur, pas une promesse). Dans DDEV, l’approche la plus stable consiste à forcer le cache Composer vers un volume persistant.

Dans .ddev/config.yaml, vous pouvez injecter des variables d’environnement au conteneur web. Exemple (à adapter à votre arborescence DDEV) :

# .ddev/config.yaml
web_environment:
  - COMPOSER_CACHE_DIR=/mnt/ddev-global-cache/composer
  - COMPOSER_HOME=/mnt/ddev-global-cache/composer-home

L’intérêt est double : (1) le cache survit aux redémarrages, (2) vous évitez de disperser des configs globales dans un $HOME de conteneur potentiellement jetable.

  • COMPOSER_HOME n’est pas qu’un cache : c’est aussi là que Composer stocke certaines configurations, dont des infos d’auth si vous choisissez de les persister (ce qu’on veut généralement éviter en équipe).
  • Sur des postes derrière un proxy d’entreprise, vous pouvez aussi devoir injecter HTTP_PROXY/HTTPS_PROXY dans web_environment (sans mettre ces valeurs dans Git).

Deuxième sujet incontournable : l’authentification vers GitHub/GitLab/Bitbucket et les limites de rate-limit. GitHub rappelle noir sur blanc la limite la plus fréquente qui vous explose en plein composer install :

“Unauthenticated requests are limited to 60 requests per hour.” — GitHub Docs (rate limits)

Concrètement, si Composer télécharge via API GitHub (dist/zip, metadata) et que vous n’avez pas de token, vous finirez avec des erreurs type API rate limit exceeded.

La méthode propre en conteneur est d’utiliser COMPOSER_AUTH (JSON) injecté via un fichier non versionné (ex : .ddev/.env) plutôt que de commiter un auth.json. Exemple :

# .ddev/.env (à ajouter à .gitignore)
COMPOSER_AUTH='{"github-oauth":{"github.com":"ghp_xxx"}}'

Puis dans .ddev/config.yaml :

web_environment:
  - COMPOSER_AUTH=${COMPOSER_AUTH}

Ça évite de persister des secrets dans l’image, et ça reste compatible avec une rotation de tokens.

Checklist “propre” (et réaliste) pour les secrets Composer en équipe :

  • Ne jamais commiter de token (ni dans auth.json, ni dans un script).
  • Stocker les secrets dans un fichier ignoré (.ddev/.env) ou dans le gestionnaire de secrets de votre OS (selon vos pratiques), puis les injecter via variables d’environnement.
  • Préférer des tokens à droits minimaux (read-only si possible) et avec expiration/rotation.
  • En CI, utiliser les secrets du fournisseur (GitHub Actions Secrets, GitLab CI Variables, etc.) plutôt qu’un token partagé dans un wiki.

PrestaShop : où Composer apporte quelque chose (et où il ne faut pas fantasmer)

Sur PrestaShop, Composer n’est pas qu’un “outil Symfony”. Sur PrestaShop 9.x, le socle Symfony 6.4 et une partie des dépendances PHP s’alignent mieux avec les pratiques Composer. Cela dit, le cœur PrestaShop reste historiquement hybride : beaucoup de boutiques “legacy” vivent avec des dépendances vendorisées, des overrides, et des modules qui n’ont jamais vu un composer.json. Donc oui, Composer dans DDEV fiabilise votre dev, mais non, ça ne “répare” pas l’architecture du core ni les modules mal packagés.

Cas d’usage concret côté projet (racine boutique) :

# Installer les dépendances selon composer.lock
ddev composer install

# Vérifier la cohérence du graphe
ddev composer validate

# Optimiser l’autoload (utile pour réduire certains temps d’I/O en dev)
ddev composer dump-autoload -o

Deux commandes très utiles quand vous déboguez une installation sur une machine “qui ne ressemble pas aux autres” :

# Vérifie les prérequis (PHP + extensions) selon composer.lock
ddev composer check-platform-reqs

# Explique pourquoi une dépendance ne peut pas être installée
ddev composer why-not vendor/package

Mini-scénario typique (vécu) : vous ajoutez une lib qui requiert ext-intl parce que votre conteneur DDEV l’a. Tout passe. Puis un collègue qui a un DDEV configuré différemment (ou une CI plus minimaliste) se prend un Your requirements could not be resolved to an installable set of packages. Avec check-platform-reqs, vous identifiez immédiatement l’écart : ce n’est pas “Composer qui bug”, c’est un runtime différent.

Pour les modules PrestaShop qui embarquent leurs propres dépendances (SDK de paiement, client API, libs métier), le pattern le moins douloureux est un composer.json au niveau du module et un vendor/ isolé dans le module. Exemple :

# Dans un module isolé
ddev exec -- bash -lc 'cd modules/ps_mymodule && composer install'

Ce choix évite de polluer le vendor/ global de la boutique et limite les collisions de versions. Il impose en contrepartie d’être discipliné sur l’autoload dans le module (PSR-4) et sur la manière dont le module charge vendor/autoload.php.

  • Si votre module est destiné à être distribué, documentez clairement si vous livrez un vendor/ “vendored” (déjà présent) ou si vous exigez un composer install côté intégrateur. Dans l’écosystème PrestaShop, les deux modèles existent, mais les mélanger sans le dire crée des surprises.
  • Quand vous testez en DDEV, testez aussi un scénario “zip de release” (comme un marchand l’installerait), pas uniquement “depuis Git + composer”.

Pour l’exécution des commandes console Symfony/PrestaShop dans le même contexte de conteneur (PHP, extensions, variables), gardez le réflexe “tout via DDEV”. À ce sujet, la liste et les options CLI côté PrestaShop sont détaillées ici : Commandes CLI PrestaShop : liste, catégories et options d’aide. L’intérêt est direct : composer installe vos outils, et vous exécutez ensuite vos commandes dans le même runtime.

Erreurs fréquentes avec DDEV Composer (et fixes reproductibles)

Premier classique : mémoire. Composer peut exploser sur des résolutions complexes, surtout avec des plugins, des contraintes larges, ou des projets multi-packages. Dans DDEV, ce n’est pas votre RAM machine qui manque, mais la configuration PHP du conteneur (memory_limit) ou les limites du process. Le contournement (temporaire) le plus explicite est :

# À n'utiliser que ponctuellement, et plutôt pour un update que pour un install “normal”
ddev exec -- bash -lc 'COMPOSER_MEMORY_LIMIT=-1 composer update'

Si vous en arrivez là souvent, le problème est ailleurs : contraintes trop permissives, dépendances incohérentes, ou plugins qui tirent des versions incompatibles.

Deuxième classique : mismatch de plateforme (version PHP/extension) entre machines de dev et CI. Composer a été conçu pour verrouiller un état via composer.lock, mais il reste sensible à la plateforme lors de la résolution. Si vous développez en PHP 8.3 dans DDEV mais que votre CI tourne en 8.2, vous pouvez introduire des packages qui ne s’installent pas ailleurs. La solution propre est de fixer la plateforme cible dans composer.json quand le projet l’exige :

{
  "config": {
    "platform": {
      "php": "8.2.0"
    }
  }
}

Ça force Composer à résoudre comme si vous étiez en PHP 8.2, même si votre conteneur est en 8.3. Évidemment, ça n’ajoute pas les extensions manquantes : si un package requiert ext-intl, il faut que l’image PHP DDEV l’ait réellement.

Astuce de méthode : quand vous devez ajuster la plateforme, faites-le en même temps qu’un composer update ciblé, pas en “vrac”. Par exemple, si le but est de rester compatible 8.2, ne lancez pas un update global sans raison : mettez à jour un package ou un groupe de packages, et observez ce que Composer veut changer.

Troisième classique (spécifique aux conteneurs et aux FS montés) : perfs I/O et incohérences de fichiers. Sur macOS/Windows, un vendor/ dense (des dizaines de milliers de fichiers) est un mauvais cas pour certains modes de montage. Si vos installs deviennent anormalement lents, testez (1) cache persistant, (2) composer install --prefer-dist, (3) optimisation autoload, et (4) un mode de perf DDEV adapté (Mutagen / NFS selon vos contraintes). Ne “réparez” pas ça en lançant Composer sur l’hôte : vous perdez précisément la reproductibilité que DDEV vous donne.

Quatrième classique (plus récent avec Composer 2.x) : plugins bloqués / allow-plugins. Dans certains projets, vous verrez des messages indiquant qu’un plugin n’est pas autorisé. Ce n’est pas un bug : c’est une mesure de sécurité. La réponse n’est pas “désactiver la sécurité”, mais autoriser explicitement les plugins nécessaires dans composer.json (et uniquement ceux-là), puis re-tester dans DDEV et en CI pour garder le comportement identique.

DDEV Composer + CI/CD : aligner local, build reproductible et audit de dépendances

Le piège le plus courant dans les équipes PrestaShop est de confondre “composer dans DDEV” (local) et “composer sur le serveur de prod” (anti-pattern). En production, exécuter Composer à la volée sur un serveur web est une prise de risque inutile : dépendance à la connectivité, à GitHub rate-limit, à des tokens, et surface d’attaque supply-chain plus grande. La pratique propre est de builder un artefact (ou une image) avec composer install --no-dev puis de déployer. Pour la partie reproductibilité d’image et pipeline, vous pouvez recouper avec : Intégration continue PrestaShop : BuildKit, GitHub Actions et build reproductible.

Côté CI, les commandes Composer utiles ne sont pas “update” (qui change la vérité), mais des commandes déterministes :

composer install --no-interaction --prefer-dist --no-progress
composer validate --no-check-all --strict
composer audit

Quelques précisions qui évitent des pipelines “flaky” :

  • Préférez composer install (avec composer.lock commité) : c’est la base de la reproductibilité.
  • Utilisez --prefer-dist en CI : en général plus rapide et plus stable que des clones VCS (sauf exceptions).
  • Si votre CI n’a pas exactement les mêmes extensions PHP que DDEV, composer install peut échouer : ce n’est pas une mauvaise nouvelle, c’est un signal d’écart à corriger (image de CI à aligner, ou plateforme à figer).

composer audit est particulièrement pertinent depuis que les advisory databases sont mieux intégrées à l’écosystème PHP. Ça ne remplace pas une vraie gestion de vulnérabilités (SCA, exceptions de risque, patch policy), mais ça attrape des erreurs grossières avant merge (par exemple une dépendance connue vulnérable introduite par mégarde).

Enfin, si vous cherchez à industrialiser la provenance et la traçabilité (SBOM, validations automatiques, politiques de versions), rattachez vos pratiques Composer à une démarche supply-chain cohérente, pas à des scripts “maison” jetables. L’article suivant est directement dans ce périmètre : CI PrestaShop : provenance, SBOM et validation automatique des modules. Le message à retenir : DDEV Composer sert à rendre votre dev local fiable, mais c’est la CI qui doit rendre votre livraison fiable.


À lire aussi