← tous les articles

Quand start-first et un volume partagé se battent pour un socket

10 juin 2026 · 2 min de lecture

docker-swarmrolloutdebugging

Mise en prod d’une nouvelle version applicative sur le cluster. Le déploiement part, puis la nouvelle tâche tombe en crash-loop au démarrage avec ce genre de message :

Another program is already listening on a port that one of our HTTP servers is configured to use.

Sauf qu’aucun port TCP n’est en conflit. Le coupable est ailleurs.

Le piège : order: start-first + un volume partagé

La stack utilise la stratégie de mise à jour start-first : Swarm démarre la nouvelle tâche avant d’arrêter l’ancienne, pour éviter toute coupure. Excellent pour la dispo… sauf que, pendant ce chevauchement, les deux tâches tournent en même temps.

Or supervisord (qui pilote nginx + php-fpm dans le conteneur) crée son socket de contrôle dans /app/var/run. Et /app/var était monté depuis un volume nommé partagé. Résultat : la nouvelle tâche trouve le socket de l’ancienne déjà en place et refuse de démarrer. Le “port” du message d’erreur, c’est ce socket Unix.

ancienne tâche ──┐
                 ├─ /app/var/run/supervisor.sock   ← un seul fichier, deux propriétaires
nouvelle tâche ──┘

Le correctif : un tmpfs par tâche

L’état runtime dans /app/var n’a aucune raison d’être partagé ni persisté : sockets, PID files, caches éphémères. La bonne réponse est un tmpfs propre à chaque tâche, qui naît et meurt avec le conteneur :

volumes:
  - type: tmpfs
    target: /app/var
    tmpfs:
      size: 134217728   # 128 Mio
      mode: 1023

Chaque tâche a désormais son /app/var privé en RAM. Plus de collision pendant le chevauchement start-first, et un bonus : zéro écriture disque pour de l’éphémère.

La leçon

Un volume nommé partagé pour de l’état runtime est un bug qui attend start-first pour se révéler. Si ce n’est ni partagé entre nœuds, ni à persister, c’est du tmpfs.

Un premier essai consistait à ne mettre en tmpfs que /app/var/run. Mauvaise idée : ça cassait les exporters de métriques qui lisaient d’autres sockets sous /app/var. La règle propre, c’est tout /app/var en tmpfs, et reconfigurer la supervision pour scraper en réseau plutôt que par socket partagé.


📬 La newsletter homelab

Les nouveaux articles + retours d'expérience self-hosting, sans spam. Désinscription en un clic.