Retour à l'accueil

Docker sur VPS : 24 conteneurs en production

L'article détaille le déploiement en production de 24 conteneurs Docker sur un VPS avec 6 GB RAM. Il couvre les principes architecturaux d'isolation, la gestion des dépendances via healthcheck, l'optimisation de l'utilisation de la mémoire pour Elasticsearch et Chrome Headless, le travail sécurisé avec des DB distantes via tunnels SSH, et la surveillance légère sans Prometheus.

24 conteneurs sur un serveur : analyse technique
Advertisement 728x90

24 Conteneurs sur un Seul VPS : Architecture Technique Haute Densité pour DevOps Intermédiaire/Sénior

Un seul serveur, 6 Go de RAM, 24 conteneurs — et tout fonctionne stablement depuis plus d'un an. Ce n'est pas une expérience, mais une infrastructure de production supportant sept projets actifs : un bot EdTech, un service anti-spam, un backend IA, un moteur de méta-recherche, une inférence locale de LLM, et deux services utilitaires. Aucun ne génère de revenus, mais tous sont critiques pour les activités opérationnelles. L'objectif n'était pas de réduire les coûts pour eux-mêmes, mais un compromis conscient : gestion manuelle au lieu de services gérés, charge prévisible au lieu d'élasticité cloud, et intégration profonde au lieu d'abstraction.

Principes Architecturaux : Isolation, Observabilité, Résilience

L'approche principale repose sur une isolation réseau stricte. Chaque projet réside dans son propre réseau Docker (bridge), éliminant les dépendances croisées et minimisant la surface d'attaque. Un réseau partagé shared est utilisé uniquement pour les services système (ex. : monitoring ou Redis commun). Les ports internes (9200, 8088, 9222) sont accessibles exclusivement via 127.0.0.1; l'accès externe est bloqué au niveau des configurations iptables et nginx.

La résilience est assurée par des dépendances healthcheck dans docker-compose.yml. Par exemple, les services PHP du projet EdTech ne démarrent pas tant qu'un tunnel SSH vers la base de données distante ne passe pas un test nc -z 127.0.0.1 3306. Cela garantit que l'application n'essaiera pas de se connecter à une base de données indisponible et ne plantera pas la file d'attente avec des erreurs.

Google AdInline article slot

L'observabilité est construite sans Prometheus/Grafana en raison des contraintes de RAM. À la place, un script bash s'exécute toutes les 15 minutes :

  • Vérifie les codes de statut HTTP des endpoints publics (/health, /webhook/advert)
  • Identifie les conteneurs malsains via docker ps --filter "health=unhealthy"
  • Surveille l'espace disque et l'utilisation du swap
  • Envoie des alertes vers un chat Telegram via curl vers l'API Bot

Cela fournit une visibilité minimale mais suffisante pour un seul administrateur.

Composants Critiques : Elasticsearch, Chrome Headless et Tunnels SSH

Trois composants définissent les limites de performance du VPS :

Google AdInline article slot
  • Elasticsearch 8.12.2 consomme 1,47 Go de RAM. Sans une limite explicite memory: 2g dans deploy.resources.limits, la JVM commence à faire du swap sur les processus voisins, causant de l'instabilité. Pour un index d'environ 50K documents et la journalisation, cela offre le meilleur équilibre entre fonctionnalité et charge. Une alternative comme Meilisearch nécessiterait de migrer les index existants et de modifier le code client, classée comme une tâche à fort effort et faible ROI à ce stade.
  • Chrome Headless (zenika/alpine-chrome) occupe 636 Mo de RAM, bien qu'il soit utilisé seulement une fois par heure pour le scraping de rendu JS. Exécuter on-demand via docker run --rm économiserait de la mémoire mais ajouterait un délai de 5 à 10 secondes par appel. Pour des services avec des SLA stricts, c'est inacceptable ; ici, c'est un compromis acceptable.
  • Tunnels SSH sont implémentés dans des conteneurs alpine séparés avec autossh. Ils fournissent un accès sécurisé à MySQL sur un hôte partagé sans ouvrir de ports externement. La configuration inclut ServerAliveInterval=30, AUTOSSH_GATETIME=0, et un healthcheck via nc. Cette solution fonctionne avec tous les hôtes supportant SSH et remplace entièrement les bases de données gérées payantes.

Optimisation Nginx et PHP : Réduire la Latence de Millisecondes

Nginx est configuré exclusivement pour les webhooks et les API — aucun fichier statique sauf /health. L'optimisation clé consiste à décharger le traitement du webhook Telegram vers un fichier PHP séparé (webhook-advert.php) qui contourne le bootstrap Laravel. Cela réduit le temps de réponse de 80–120 ms à 15–25 ms, ce qui est critique lors d'appels massifs de webhooks depuis l'API Telegram (délai maximal — 60 secondes).

La configuration inclut également :

  • Redirection forcée HTTP → HTTPS
  • Refus de traiter tout chemin autre que /health, /webhook/, et /api/telegram/
  • Augmentation de fastcgi_read_timeout à 120 secondes pour les tâches longues
  • Utilisation de realpath_root pour une gestion correcte de index.php

SSL et Sécurité : Trois Stratégies sur un Hôte Unique

La terminaison SSL est organisée de manière hybride :

Google AdInline article slot
  • getssl + Let's Encrypt — pour les domaines nécessitant un chiffrement de bout en bout sans Cloudflare
  • Proxy Cloudflare — pour la plupart des domaines : la terminaison SSL se fait au bord, le trafic vers le VPS passe en HTTP, mais est protégé par un filtrage IP (seul ASN Cloudflare autorisé)
  • Mise à jour Manuelle — une mesure temporaire pour le backend IA, actuellement en cours d'automatisation via Caddy

La configuration Cloudflare inclut Always Use HTTPS, WAF, et Rate Limiting (100 requêtes/min par IP) obligatoires, compensant l'absence de WAF côté VPS.

Points Clés

  • Une isolation réseau stricte via des réseaux Docker séparés empêche les défaillances en cascade et simplifie les audits de sécurité.
  • Les dépendances healthcheck dans docker-compose garantissent que les services ne démarrent que lorsque leurs dépendances sont prêtes (ex. : tunnel SSH vers la DB).
  • Elasticsearch nécessite une limite de mémoire dure (2 Go) ; sinon, la JVM fait du swap sur les conteneurs voisins, déclenchant le tueur OOM.
  • Garder Chrome Headless en mode toujours actif est justifié à faible fréquence d'utilisation si la latence de démarrage est critique pour la logique métier.
  • Le monitoring Bash avec alertes Telegram est un remplacement fonctionnel pour Prometheus/Grafana sous contraintes de RAM, à condition que les SLO soient clairement définis.

— Editorial Team

Advertisement 728x90

Lire ensuite