Mettre un site Drupal sous conteneurs change surtout trois choses : l’environnement devient reproductible, les dépendances sont isolées et le déploiement cesse de dépendre de la machine de chacun. Je vais montrer comment organiser une pile propre avec Docker, comment choisir entre une approche brute et des outils plus cadrés comme DDEV, et où se cachent les pièges qui font perdre du temps en équipe. L’objectif n’est pas de faire tourner Drupal dans un conteneur pour le principe, mais de gagner un vrai confort de développement et de mise en production.
Les repères à garder en tête avant de bâtir la pile
- Pour les versions récentes de Drupal, je pars sur PHP 8.3 et une base de données supportée dès le départ.
- La bonne architecture sépare le web, PHP, la base, les fichiers persistants et les tâches planifiées.
- En local, DDEV est souvent le chemin le plus rapide ; Compose brut reste utile quand il faut garder la main sur chaque brique.
- En production, une image immuable et des volumes bien pensés valent plus qu’un empilement de conteneurs.
- Les problèmes les plus coûteux viennent des services non prêts, des permissions de fichiers et des volumes mal gérés.
Pourquoi conteneuriser Drupal change la manière de livrer un site
Je vois surtout un bénéfice très concret : on arrête de confondre le code de l’application avec l’état de la machine. Quand PHP, les extensions, le serveur web et la base de données vivent dans des conteneurs séparés, les écarts entre le poste du développeur, la CI et la production se réduisent nettement. C’est là que la logique DevOps devient utile : on standardise, on automatise et on teste le même environnement tout au long du cycle de vie.
Le second avantage est moins visible mais souvent décisif : un site Drupal devient plus simple à faire évoluer. Je peux monter une nouvelle version de PHP, changer de moteur SQL, ajouter Redis ou isoler le cron sans réinstaller toute la machine. En pratique, ça réduit les frictions d’onboarding, les bugs “ça marche chez moi” et les déploiements bricolés à la main.
Mais il y a une limite que j’aime rappeler : Docker ne compense pas une architecture floue. Si la persistance, la configuration propre et les contrôles de santé sont mal pensés, les conteneurs ne font que rendre le problème plus reproductible. Une fois ce cadre posé, il faut regarder la forme d’une pile Drupal raisonnable.

À quoi ressemble une architecture saine
Quand j’assemble une pile Drupal, je cherche d’abord à séparer les responsabilités. Le web ne doit pas faire le travail de la base, la base ne doit pas contenir le code, et les fichiers envoyés par les utilisateurs ne doivent pas disparaître à chaque redémarrage. La structure la plus lisible ressemble souvent à cela.
| Composant | Rôle | Ce que je vérifie |
|---|---|---|
| Serveur web | Termine les requêtes HTTP, sert les fichiers statiques et relaie le PHP | Cache des assets, compression, règles de réécriture adaptées à Drupal |
| PHP-FPM | Exécute le code PHP du site | Version PHP alignée avec Drupal, extensions requises, OPcache activé |
| Base de données | Stocke le contenu, la configuration et l’état applicatif | Version supportée, volume persistant, sauvegarde testée |
| Volume des fichiers | Conserve les médias et les uploads | Persistance, droits d’écriture, taille prévisible |
| Cache ou sessions | Réduit la charge sur la base et accélère le back-office | Redis ou équivalent si le site commence à grossir |
| Cron ou worker | Lance les tâches planifiées et les traitements différés | Exécution séparée du trafic web pour éviter les blocages |
Dans les sites un peu plus ambitieux, j’ajoute parfois une brique de recherche dédiée ou un proxy inverse devant l’ensemble, mais je ne le fais pas par réflexe. Je le fais seulement quand le besoin métier le justifie. Une fois ce schéma en tête, la vraie question devient : comment le traduire dans une configuration de conteneurs propre et maintenable ?
Construire une base saine avec Docker Compose
Pour moi, Docker Compose reste la manière la plus claire de décrire une application Drupal multi-services. La documentation de Docker rappelle qu’un service peut démarrer avant d’être réellement prêt, ce qui change tout dès qu’une base de données entre dans l’équation. Je ne me contente donc jamais d’un simple ordre de démarrage ou d’un depends_on naïf.
- Je fixe les versions de PHP et de la base de données pour éviter les surprises à la mise à jour.
- Je sépare le code et les données : le code peut être reconstruit, les médias et la base doivent être persistants.
- Je déclare des contrôles de santé pour le web et la base, afin de savoir quand un service est vraiment utilisable.
- Je garde les secrets hors de l’image : mot de passe de base, clés d’API et accès SMTP ne doivent pas vivre dans le dépôt.
- Je prépare deux contextes, un pour le local et un pour la livraison, plutôt qu’un seul Compose qui tente de tout faire.
Sur les versions récentes de Drupal, je pars sur PHP 8.3. Côté base, je vérifie aussi les versions supportées par le projet : MySQL 8.0, MariaDB 10.6 ou PostgreSQL 16 pour les branches actuelles. Si j’utilise PostgreSQL, je n’oublie pas l’extension pg_trgm, qui est souvent oubliée au premier déploiement et qui finit par bloquer des fonctionnalités de recherche ou de filtrage.
Je privilégie aussi des images de base simples, puis j’ajoute seulement les extensions PHP réellement nécessaires. C’est plus propre que de partir d’une image surchargée qu’on ne comprend plus au moment du patching. Le bon réflexe, ici, n’est pas de multiplier les couches, mais d’être explicite sur ce que chaque service apporte. Reste à savoir si l’on veut tout écrire soi-même ou s’appuyer sur une solution plus cadrée.
Choisir entre Compose brut, DDEV, Lando et Docker4Drupal
La vraie décision n’est pas “Docker ou pas Docker”. C’est plutôt : quelle abstraction réduit le plus la complexité sans me masquer ce que je dois contrôler ? Sur Drupal, je ne traite pas toutes les options de la même manière. Pour du local, je privilégie souvent un outil déjà pensé pour l’écosystème Drupal ; pour une production sur mesure, je veux parfois revenir à Compose pur.
| Outil | Quand je le choisis | Atout principal | Limite |
|---|---|---|---|
| Compose brut | Équipe DevOps à l’aise avec les images et les volumes | Contrôle total, peu d’opinion cachée | Demande plus de maintenance et de discipline |
| DDEV | Développement local Drupal sur macOS, Linux ou Windows | Démarrage rapide, conventions solides, faible friction | Plus directif, donc moins libre |
| Lando | Projets où plusieurs services doivent être déployés vite | Bonne ergonomie pour des piles hétérogènes | Ajoute une couche d’abstraction supplémentaire |
| Docker4Drupal | Besoin d’une base de pile Drupal déjà cadrée | Configuration orientée Drupal et services prêts à l’emploi | Il faut quand même comprendre ce qu’il y a sous le capot |
Pour être clair, je pars presque toujours sur DDEV pour le local quand l’objectif est d’aller vite sans sacrifier la cohérence. C’est aussi l’option que la documentation Drupal met en avant comme environnement recommandé pour le développement local. En revanche, dès qu’un projet a des contraintes spécifiques de sécurité, de réseau ou de déploiement, Compose brut redevient intéressant parce qu’il me laisse décider de chaque détail. Le point clé, ensuite, est de faire du poste local un vrai reflet du cycle de vie du site.
Faire du local un miroir utile du déploiement
Le local doit ressembler à la production sur les points qui comptent, sinon on déplace simplement les bugs plus loin dans le pipeline. J’essaie de garder la même version de PHP, le même moteur de base et une logique de configuration claire, tout en laissant au local les outils de confort comme le débogage ou les montages de fichiers plus souples.
- Je sépare la configuration locale avec un fichier d’override ou un équivalent, pour activer le debug sans contaminer la prod.
-
Je garde
sites/default/filesdans un volume persistant, parce que c’est le point de rupture le plus fréquent après un redéploiement. - Je lance Drush dans le conteneur adéquat, pour exécuter les commandes au plus près de l’environnement réel.
- Je traite le cron à part, soit via un service dédié, soit via une tâche planifiée de l’orchestrateur.
- Je réserve Xdebug au local, pour éviter d’alourdir inutilement la production.
- Je limite les montages massifs sur les machines où les bind mounts coûtent cher en performances.
Je fais aussi attention à un piège classique : activer trop de raccourcis en local, puis oublier de les enlever en préproduction. Le cache, la journalisation, le mode debug et les permissions doivent être pensés comme des variantes contrôlées, pas comme des réglages improvisés. Quand cette discipline est en place, le passage en production devient beaucoup plus mécanique.
Passer en production sans transformer les conteneurs en piège
En production, je pars d’une règle simple : l’image contient l’application, le volume contient les données. Le code doit être reconstruit de manière reproductible, idéalement dans la CI, puis publié comme un artefact versionné. Les données de Drupal, elles, doivent rester séparées et sauvegardées explicitement. C’est ce découplage qui rend les retours arrière et les mises à jour beaucoup moins risqués.
Pour les sites gérés par Composer, je préfère résoudre les dépendances au moment du build, pas au démarrage du conteneur runtime. Cela me donne une image plus stable, plus facile à tester et plus simple à promouvoir d’un environnement à l’autre.
- Je construis l’image à partir d’un commit ou d’un tag précis.
- Je lance les tests et je valide la compatibilité PHP et base de données avant publication.
- Je déploie l’image immuable, puis j’exécute les mises à jour Drupal nécessaires, y compris l’import de configuration et le rebuild du cache si le site l’utilise.
- Je vérifie le statut des services avec des contrôles de santé avant d’ouvrir le trafic.
- Je garde les secrets hors du dépôt et je les injecte au moment du déploiement.
Je préfère aussi un reverse proxy dédié devant le conteneur web, avec TLS terminé proprement et des en-têtes cohérents. Quand c’est possible, je réduis les droits du conteneur web au strict nécessaire. Si le site grossit, j’ajoute des limites de ressources, de la journalisation centralisée et parfois Redis pour soulager les sessions ou le cache. Je ne passe pas à Kubernetes ou à une autre couche plus lourde par réflexe ; pour un site unique, un Compose bien tenu reste souvent plus rentable. Une pile qui tourne sans erreur visible mais qui ne redémarre pas proprement, qui ne se sauvegarde pas et qui ne se met pas à jour proprement n’est pas une bonne production, c’est juste une accalmie temporaire.
Les erreurs que je vois le plus souvent sur les projets Drupal conteneurisés
Je retrouve souvent les mêmes défauts, et ils coûtent tous du temps au moment où il faut livrer ou restaurer le site. Le plus frustrant, c’est qu’ils sont faciles à éviter dès le début si l’équipe prend deux ou trois décisions fermes.
- Monter tout le projet en production : on gagne en simplicité apparente, mais on perd en reproductibilité et en sécurité de déploiement.
- Oublier le volume des fichiers : les médias disparaissent dès qu’un conteneur est recréé.
- Se fier à l’ordre de démarrage : une base “lancée” n’est pas forcément prête à répondre aux requêtes.
- Garder la même configuration pour tout : le debug, le cache et les permissions ne doivent pas être identiques partout.
- Négliger la compatibilité des versions : un changement de PHP, de base ou d’extension peut casser un site pourtant stable en apparence.
- Ne pas tester la restauration : une sauvegarde inutilisée reste une hypothèse, pas une preuve.
Le fil conducteur est toujours le même : les conteneurs ne corrigent pas une mauvaise gestion de l’état. Ils la rendent juste plus visible. C’est aussi ce qui rend une pile bien pensée plus facile à maintenir au fil des mois.
La version pragmatique que je garderais en tête pour le prochain déploiement
Si je devais résumer ma façon d’aborder Drupal sous conteneurs, je dirais ceci : je simplifie le local, je versionne l’image, je sépare les données et je teste les dépendances avant de toucher au trafic réel. Cette approche est moins spectaculaire qu’une pile ultra sophistiquée, mais elle donne des déploiements plus calmes et des retours arrière plus propres.
Avant le prochain déploiement, je vérifierais quatre choses : la version de PHP, la persistance des volumes, le contrôle de santé des services et la procédure de restauration. Si ces quatre points sont clairs, la plupart des incidents courants deviennent des détails gérables. Le bon design n’est pas celui qui impressionne en démonstration ; c’est celui qui reste compréhensible quand il faut corriger vite un site Drupal en production.