Conteneuriser votre site : configuration Docker, optimisation des images, orchestration et limites de ressources
1. Pourquoi conteneuriser un site autonome plutôt que de tout installer directement sur le serveur
Installer PHP, Nginx et MySQL directement sur un VPS fonctionne, mais trois problèmes surgissent au bout de six mois. D’abord, un nouveau collaborateur met deux jours à configurer son environnement. Ensuite, pour migrer d’Aliyun vers Tencent Cloud, il faut réinstaller toutes les dépendances. Enfin, lors d’une mise à jour de sécurité, on n’ose pas toucher à la version en production. Docker empaquette l’application et ses dépendances dans une image immuable, et c’est précisément ce qu’il résout.
Un critère simple : si votre documentation de déploiement contient « d’abord apt install php8.3-fpm, puis installez ces 12 extensions, puis modifiez ces 8 lignes de php.ini », c’est que vous avez besoin de conteneuriser. Mettez ces 12 extensions et ces 8 réglages dans le Dockerfile : n’importe quelle machine les reproduira ensuite avec un simple docker run. Pour l’articulation avec le CDN et les ressources statiques, voir Accélération mondiale par CDN.
| Modes de déploiement | Coût de reproduction de l’environnement | Migration de serveur | Vitesse de rollback | Taille adaptée |
|---|---|---|---|---|
| Installation directe sur le VPS | 2 jours-homme | Réinstaller toutes les dépendances | Via snapshot, 30 minutes | Phase de prototype |
| Installation par script Shell | 0,5 jour-homme | Exécution du script, écarts persistants | 15 minutes | Site unique en production depuis 1 an |
| Image Docker | 5 minutes | Pull de l’image et exécution | Changement de tag, 3 minutes | Site en production, environnements multiples |
| Orchestration Docker Compose | 5 minutes | Copie du yaml et exécution | Rollback en un clic | Application + base de données + file d’attente |
2. Comment écrire un Dockerfile sans le gonfler
L’erreur la plus fréquente dans un Dockerfile de site autonome, c’est le build mono-étape : FROM ubuntu, puis installation de PHP, installation de Composer, composer install, COPY du code source, exposition du port. Les images produites ainsi dépassent souvent 1 Go, car elles embarquent les outils de compilation, le cache npm et le dossier .git. La bonne approche est le build multi-étapes : la première étape utilise une image builder pour compiler le front-end et installer les dépendances composer ; la seconde ne copie dans l’image alpine que les artefacts compilés et le runtime.
Quelques règles strictes : choisissez alpine plutôt qu’ubuntu comme image de base ; le .dockerignore doit exclure node_modules, .git, .env et le répertoire d’upload ; ajoutez –no-dev et –no-cache à npm/composer install ; exécutez l’application avec un utilisateur non-root. Objectif de taille d’image : rester sous 200 Mo pour une application PHP/Node pure, et sous 400 Mo avec des ressources statiques. Pour l’analyse des images et la base de sécurité, voir Sauvegarde et restauration : s’entraîner à réagir.
Un cas concret : une équipe découvre six mois après la mise en production que son image pèse 1,4 Go. En inspectant les couches avec docker history, elle constate que composer install n’avait pas l’option –no-dev, embarquant phpunit et toutes les dépendances de développement dans l’image de production ; et que COPY . . avait aussi copié le répertoire .git. Après passage à un build multi-étapes, l’étape builder installe les dépendances et l’étape d’exécution ne copie que le répertoire vendor et le répertoire public : l’image tombe à 180 Mo et le déploiement passe de 3 minutes à 40 secondes.
| Niveau | Erreur fréquente | Écriture optimisée | Gain de taille |
|---|---|---|---|
| Image de base | FROM ubuntu:22.04 | FROM php:8.3-fpm-alpine | environ 400 Mo |
| Dépendances système | apt-get install build-essential | Build multi-étapes, installation dans l’étape builder | environ 200 Mo |
| Dépendances PHP | composer install | composer install –no-dev –no-cache | environ 80 Mo |
| Dépendances front-end | COPY . . | npm ci && npm run build dans l’étape builder | environ 300 Mo |
| Répertoire source | COPY . /var/www | COPY –from=builder /app/public ./public | environ 100 Mo |
| Utilisateur d’exécution | exécution en root | RUN adduser -D app | gain de sécurité, pas de taille |
III. Comment orchestrer un site indépendant avec docker compose
L’architecture type d’un site indépendant repose sur quatre conteneurs : Nginx en reverse proxy, l’application PHP-FPM ou Node, MySQL/PostgreSQL et Redis. Un seul docker-compose.yml relie ces quatre services, un volume persistant conserve les données MySQL, seuls les ports 80 et 443 de Nginx sont exposés, les autres services communiquent sur le réseau interne. N’exposez pas le port MySQL sur Internet.
Un extrait de configuration prêt à l’emploi : Nginx depends_on php, php depends_on db et redis ; le healthcheck exécute curl -fsS http://localhost/health toutes les 30 secondes ; la politique de redémarrage est unless-stopped pour tous. Pour la sauvegarde, montez régulièrement le volume de données MySQL vers un répertoire de sauvegarde sur l’hôte, puis synchronisez-le à distance avec rsync. Pour le monitoring d’une orchestration multi-conteneurs, voir Surveillance et alertes du site.
Exemple concret : un serveur léger Alibaba Cloud de 4 cœurs et 8 Go fait tourner trois conteneurs WordPress, MySQL et Redis. Le conteneur MySQL monte un named volume pour stocker les données, Nginx mappe les ports 80 et 443 sur l’hôte, le conteneur WordPress n’expose aucun port et passe uniquement par le réseau interne. Après un redémarrage de l’hôte, docker compose up -d relance automatiquement les trois services, sans avoir à se connecter pour démarrer quoi que ce soit à la main. C’est la valeur la plus simple de compose.
| Services | Image de base | Limite CPU | Limite mémoire | Persistance |
|---|---|---|---|---|
| nginx | nginx:1.27-alpine | 0,5 cœur | 128 Mo | Non |
| php-fpm / node | php:8.3-fpm-alpine | 1 à 2 cœurs | 512 Mo à 1 Go | non (volume monté pour les uploads) |
| mysql | mysql:8.4 | 1 à 2 cœurs | 1 à 2 Go | oui (répertoire data) |
| redis | redis:7-alpine | 0,5 cœur | 256 Mo | oui (persistance AOF) |
| cron/file d’attente | même image que l’application | 0,5 cœur | 256 Mo | Non |
4. Limites de ressources : un conteneur sans plafond finit par étouffer toute la machine
Beaucoup de gens utilisent Docker pour se simplifier la vie et ne précisent ni –cpus ni –memory au démarrage. Résultat : dès que PHP-FPM rencontre une requête lente, la mémoire passe de 512 Mo à 4 Go et pousse le MySQL hébergé sur la même machine à l’OOM. Chaque conteneur doit déclarer explicitement ses limites de ressources, c’est une obligation.
Repères de quota pour un site en propre : conteneur applicatif 1 à 2 cœurs de CPU, 512 Mo à 1 Go de mémoire ; conteneur MySQL selon le volume de données, 1 cœur et 1 Go suffisent en dessous de 10 Go ; Nginx et Redis 0,5 cœur et 128 à 256 Mo chacun. Réservez 20 % de marge sur l’hôte pour le daemon Docker et le système. Un critère simple : 80 % de la mémoire totale de l’hôte allouée aux conteneurs, 20 % au système ; au-delà de ce ratio, ajoutez une machine. Allouez le CPU en fonction des pics, pas de la moyenne : le trafic d’un site en propre connaît des pics en semaine et des creux la nuit, dimensionner sur la moyenne provoque des files d’attente aux heures de pointe.
| Taille du site | Configuration recommandée | Allocation CPU | Allocation mémoire | Visites mensuelles indicatives |
|---|---|---|---|---|
| Phase de validation | 1 VPS 2 cœurs 2 Go | App 1 cœur + DB 0,5 cœur | App 512 Mo + DB 1 Go | <50 000 |
| Phase de croissance stable | 1 VPS 4 cœurs 8 Go | App 2 cœurs + DB 1,5 cœur | App 2 Go + DB 4 Go | 50 000 à 300 000 |
| Pic multilingue | 2 × 4 cœurs 8 Go | App 2 cœurs par machine | 2 Go par machine, DB 4 Go à part | 300 000 à 1 million |
| Pic du jour de promotion | App étendue horizontalement à 3 ou 4 machines | 2 cœurs par machine | 2 Go par machine | Trafic salon et promotion |
5. Quand passer à Swarm ou K8s
La conclusion contre-intuitive est la suivante : 90 % des sites en propre n’ont pas besoin de K8s. docker compose fait tourner 4 à 8 conteneurs sur un seul VPS, de quoi tenir un site B2B jusqu’à 100 000 visites par jour. Ne passez à Swarm que si l’un de ces trois signaux apparaît : besoin de faire tourner l’application sur plus de deux VPS, besoin de basculer automatiquement le trafic en déploiement bleu-vert, besoin de redémarrer automatiquement les conteneurs tombés via les health checks.
Le critère est simple : si votre docker-compose.yml dépasse 30 services, ou si plus de 5 personnes maintiennent cet environnement en même temps, envisagez un orchestrateur. Sinon, compose reste la meilleure solution : consacrer à la rédaction et au SEO l’énergie que demanderait la maintenance de K8s rapporte davantage.
La difficulté de K8s, c’est qu’il faut une personne dédiée à la maintenance d’etcd, des plugins réseau et du contrôleur Ingress, et le seul dépannage prend une journée par semaine. Pour une petite équipe, il est plus rentable de consacrer ce temps à la rédaction et au SEO. Si vous devez vraiment déployer plusieurs instances à l’avenir, la conception de l’équilibrage de charge est détaillée dans Équilibrage de charge et déploiement multi-instances.
| Outil d’orchestration | Temps d’apprentissage | Coût de maintenance | Nombre de nœuds adapté | Quand le choisir |
|---|---|---|---|---|
| docker compose | 1 à 2 jours | Très faible | 1 instance | Premier choix pour 90 % des sites en propre |
| docker swarm | 3 à 5 jours | Faible | 2 à 10 machines | Besoin d’orchestration multi-machines et de mises à jour progressives |
| K8s | 2 à 4 semaines | Élevée | Plus de 5 machines | Plusieurs équipes, plusieurs services, mise à l’échelle automatique |
| K8s managé par un cloud | 1 à 2 semaines | Moyenne | Plus de 10 machines | DevOps dédié déjà en place |
FAQ — Questions fréquentes
Docker est-il plus lent qu’une installation directe sur serveur pour un site en propre ?
Quelle taille d’image est raisonnable ?
docker compose tient-il 100 000 visites par jour ?
Comment gérer les logs et les fichiers uploadés dans les conteneurs ?
Quand passer à K8s, quand rester sur compose ?
Une image alpine peut-elle manquer de dépendances et ne pas démarrer ?
Pour conclure
La conteneurisation apporte 80 % de sa valeur à un site e-commerce indépendant par la cohérence des environnements, et 20 % par l’orchestration. Commencez par écrire correctement le Dockerfile, compresser l’image sous 200 Mo et bien gérer vos quatre services dans le fichier compose : vous réglez ainsi le problème le plus douloureux de votre stack, la dérive des environnements. Ne vous précipitez pas sur K8s, c’est un autre métier à plein temps.
Feuille de route : la première semaine, écrivez un Dockerfile multi-étapes et faites passer l’image de 1 Go à 200 Mo ; la deuxième, orchestrez Nginx + application + MySQL + Redis avec compose, en montant correctement les volumes de données ; la troisième, branchez le pipeline CI/CD sur le registre d’images pour qu’un push de code déclenche automatiquement la création de l’image. Ces trois étapes faites, la migration d’un serveur passe de deux jours à deux heures. Pour l’articulation avec le CDN et la supervision, voir Accélération mondiale par CDN. Au quotidien, un coup d’œil hebdomadaire à docker system df pour nettoyer les images orphelines évite que le disque se remplisse peu à peu d’images inutiles.
Une phrase à retenir : la première étape de la conteneurisation n’est pas de passer à K8s, mais de pouvoir lancer votre site sur n’importe quel serveur vierge avec une seule commande.
