Le premier article de cette série l’a prouvé par les chiffres : Redis Object Cache apporte un gain constant de ~+7% et −25 ms sur toutes les pages où PHP s’exécute réellement – admin, pages dynamiques, utilisateurs connectés. Maintenant, comment on passe de « ça marche en local » à « c’est en prod sur tous les projets » ?
Voici le pipeline complet : extension du template GitLab CI/CD Bedrock existant, rôle Ansible, container Redis partagé entre projets – et les quatre pièges concrets rencontrés en route.
Architecture cible
L’objectif était simple : un container Redis partagé entre tous les projets de l’infra, sans toucher à l’architecture existante de chaque projet. Voici ce que ça donne :
- Container Redis (
redis:7-alpine) déployé via Ansible sur le réseau Dockerdb, commun à tous les projets - Chaque container WordPress connecté au réseau
dben plus de ses réseaux habituels - Côté app : extension PHP
redisdans leProd.Dockerfile, pluginwp-redis/redis-cache:2.7.0via Composer, constantesWP_REDIS_HOST/WP_REDIS_PORTlues depuis les variables d’environnement dansconfig/application.php
Un point important : object-cache.php est ignoré dans .gitignore. Ce drop-in est généré par WP-CLI au déploiement – pas question de le versionner, il dépend de l’environnement.
Le template GitLab CI
Plutôt que de modifier le template Bedrock existant, j’ai créé un template d’extension .wordpress-bedrock-redis-template.yml – une approche non-breaking qui s’inclut dans les projets qui en ont besoin sans impacter les autres.
Deux variables avec valeurs par défaut, surchargeables par projet :
REDIS_HOST: redis # valeur par défaut
REDIS_PORT: 6379 # valeur par défaut
La séquence de déploiement étend celle du template Bedrock dans cet ordre :
- Mise en place des permissions
- Flush WP Rocket (si installé)
- Activation Redis + enable + flush (si installé)
- Flush des rewrites
Les conditions « si installé » sont importantes : le template reste utilisable sur des projets sans Redis ou sans WP Rocket sans lever d’erreur.
Le rôle Ansible
Le rôle Ansible déploie le container Redis et prépare l’infrastructure. Deux tâches clés à ne pas rater :
Création idempotente du réseau Docker db en pre_task – ce réseau n’existait pas au premier déploiement, et Ansible échouait silencieusement si le container essayait de s’y connecter avant sa création.
Pré-création du volume de données avec le bon owner – le répertoire de données Redis doit appartenir à l’uid 999 (l’utilisateur redis dans le container). Si Docker le crée automatiquement en root, Redis démarre mais bloque toutes les écritures avec l’erreur stop-writes-on-bgsave-error. Solution : créer le répertoire manuellement avec owner: 999 avant de démarrer le container.
Les quatre pièges rencontrés
La mise en prod s’est faite sans grosse surprise – sauf trois points qui méritent d’être documentés.
1. Réseau Docker db inexistant au premier déploiement. Le réseau partagé entre projets doit être créé avant que les containers essaient de s’y connecter. Résolu avec une pre_task de création idempotente – si le réseau existe déjà, Ansible ne fait rien.
2. Répertoire de données Redis créé en root par Docker. Docker crée le répertoire monté en volume avec les permissions du processus qui le crée – root par défaut. Redis (uid 999) ne peut pas écrire dedans et bloque toutes les opérations de persistance. Solution : pré-créer le répertoire dans le playbook Ansible avec owner: 999 avant de démarrer le container.
3. wp redis enable échouait silencieusement. La commande WP-CLI pour activer le drop-in échoue si le plugin Redis Object Cache n’est pas activé dans WordPress – même s’il est installé via Composer. Résolu en ajoutant un check wp plugin is-installed suivi d’une activation conditionnelle avant le wp redis enable.
4. Cache Redis partagé entre projets faute de préfixe. Quand plusieurs projets WordPress pointent vers le même container Redis – ce qui est exactement le cas dans cette architecture – ils écrivent dans le même espace de noms par défaut. Résultat : le temps d’un déploiement, le cache s’est retrouvé partagé entre deux projets en prod et deux en staging. Les données d’un projet écrasaient celles d’un autre.
La correction est simple mais non négociable dès qu’on partage une instance Redis entre plusieurs projets :
define( 'WP_REDIS_PREFIX', 'my_project_my_env' );
À définir dans config/application.php avec un préfixe unique par projet ET par environnement – sosmed_prod, sosmed_staging, juzed_prod… Le préfixe est ajouté à toutes les clés Redis du projet, ce qui garantit une isolation totale entre les instances qui partagent le même container.
À ajouter dans le template GitLab CI comme variable obligatoire – pas optionnelle. Si elle n’est pas définie, le pipeline devrait échouer explicitement plutôt que de laisser un projet tourner sans isolation.
État final
Sur staging et prod, wp redis status retourne :
Status: Connected
Drop-in: Valid
Disabled: No
Redis est opérationnel sur juzed.dev. Le template GitLab est réutilisable sur tous les projets de la stack – une inclusion dans le .gitlab-ci.yml du projet et deux variables d’environnement à définir, c’est tout.
Ce que j’aurais fait différemment
Documenter les pièges Ansible avant de déployer. Les erreurs silencieuses de configuration (mauvais nom de dossier, mauvaises permissions) sont les plus chronophages – pas parce qu’elles sont complexes à corriger, mais parce qu’elles ne lèvent pas d’erreur explicite. Un playbook de vérification pré-déploiement qui valide la structure du rôle et les permissions des volumes aurait économisé du temps.
La série continue : prochains benchmarks sur un projet Elementor et sur un projet avec espace membres en front. Les résultats devraient être sensiblement différents – Redis devrait y prendre beaucoup plus d’importance.
Stack : WordPress FSE · Bedrock · Timber/Twig · Redis Object Cache 2.7.0 · Redis 7-alpine · GitLab CI/CD · Ansible · Docker · Traefik · WP-CLI