Dépannage

Mise à jour de Docker : quand un conteneur ne redémarre pas tout seul

restart: unless-stopped ne suffit pas : après une mise à jour de containerd ou un arrêt de la machine, des conteneurs restent arrêtés. La cause et la parade.

Mis à jour le 15 octobre 2026 · ⏱ 7 min de lecture

Une nuit d’octobre, la mise à jour automatique du système a installé une nouvelle version de Docker. Docker a redémarré, tous mes conteneurs sont repartis… sauf Traefik, le reverse proxy. Résultat : tous les sites du serveur sont restés inaccessibles pendant plus d’une journée. Voici ce qui s’est passé et comment l’éviter.

Ce qui s’est passé

  1. À 4 h, la mise à jour automatique du système trouve une nouvelle version de docker-ce et containerd.
  2. L’installation redémarre le service Docker, qui arrête proprement tous les conteneurs.
  3. Docker redémarre et relance les conteneurs marqués restart: unless-stopped.
  4. Traefik, lui, est resté à l’état Exited (0) : arrêté proprement, jamais relancé. Les logs de Docker n’expliquent pas pourquoi.

Dans les logs, on voyait seulement :

Container failed to exit within 10s of signal 15 - using the force
Cannot connect to the Docker daemon at tcp://socket-proxy:2375. Is the docker daemon running?

Deux messages normaux pendant un redémarrage de Docker (fiche 1, fiche 2), qui ne signalent pas le vrai problème : un conteneur qui ne revient pas.

La vraie cause, reproduite

En rejouant la scène sur un serveur de test (Ubuntu 26.04, Docker 29), le mécanisme est apparu clairement :

  • un simple systemctl restart docker ne pose aucun problème : tout repart ;
  • mais si containerd (le moteur qui fait réellement tourner les conteneurs, sous Docker) s’arrête avant Docker, chaque conteneur s’arrête proprement, avec le code 0… et Docker, en redémarrant, n’en relance aucun, malgré restart: unless-stopped.

Ce cas arrive dans deux situations très banales : la mise à jour du paquet containerd.io (souvent en même temps que Docker), et l’arrêt de la machine, quand containerd est arrêté en premier. Sur le serveur de production, seuls les conteneurs les plus rapides à s’arrêter, dont Traefik, sont restés à terre ; sur le serveur de test, c’était tous.

La leçon

restart: unless-stopped couvre les plantages et les redémarrages du serveur. Ce n’est pas une garantie qu’un conteneur reparte après une mise à jour de Docker ou de containerd. Et le reverse proxy est le point unique de panne : s’il tombe, tout tombe.

Bon à savoir : depuis octobre 2026, le script de Mon serveur installe automatiquement la protection 2 ci-dessous (option « Relance automatique des conteneurs », activée par défaut) : elle se déclenche 20 secondes après chaque démarrage de Docker, puis toutes les 15 minutes. Testée en reproduisant l’incident : les 12 conteneurs arrêtés sont repartis en moins d’une minute.

Vérifier maintenant

Y a-t-il des conteneurs arrêtés sur votre serveur ?

sudo docker ps -a --filter status=exited --format "table {{.Names}}\t{{.Status}}"

Pour en relancer un :

sudo docker start traefik

Protection 1 : relancer après chaque mise à jour

Si vous mettez à jour le système avec un script, notez les conteneurs en marche avant, et relancez ceux qui manquent après :

avant=$(docker ps --format '{{.Names}}' | sort)

apt-get -y full-upgrade

# Docker peut mettre un moment à revenir
for i in $(seq 24); do docker info >/dev/null 2>&1 && break; sleep 5; done
sleep 20
for c in $(comm -23 <(echo "$avant") <(docker ps --format '{{.Names}}' | sort)); do
  docker start "$c" && echo "Relancé : $c"
done

Protection 2 : un gardien qui relance

Un petit script lancé toutes les 15 minutes relance tout conteneur arrêté alors qu’il devrait tourner, et vous prévient :

sudo tee /usr/local/bin/relance-conteneurs >/dev/null <<'EOF'
#!/bin/bash
# Relance les conteneurs « unless-stopped » ou « always » qui sont arrêtés.
for c in $(docker ps -aq --filter status=exited); do
  pol=$(docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' "$c")
  [[ "$pol" == "unless-stopped" || "$pol" == "always" ]] || continue
  name=$(docker inspect -f '{{.Name}}' "$c" | tr -d /)
  docker start "$c" >/dev/null && logger -t relance-conteneurs "relancé : $name"
done
EOF
sudo chmod 755 /usr/local/bin/relance-conteneurs
echo "*/15 * * * * root /usr/local/bin/relance-conteneurs" | sudo tee /etc/cron.d/relance-conteneurs

Pour voir ce qu’il a fait : journalctl -t relance-conteneurs. Ajoutez une notification (ntfy ou Discord) à la place de logger pour être prévenu.

Pour arrêter volontairement une application, utilisez désormais docker compose down (le conteneur est supprimé, le gardien ne le voit plus) plutôt que docker compose stop (le conteneur reste, arrêté, et serait relancé). Vos données ne sont pas touchées dans les deux cas.

Protection 3 : surveiller de l’extérieur

Le serveur ne peut pas signaler sa propre panne totale. Surveillez vos sites depuis une autre machine : Uptime Kuma sur un Raspberry Pi à la maison, ou un service gratuit en ligne. Dans cet incident, c’est une surveillance externe qui aurait permis de réagir en minutes plutôt qu’en heures.

À retenir

  • Après une mise à jour de Docker ou un redémarrage, vérifiez docker ps -a --filter status=exited.
  • Automatisez cette vérification : une ligne de cron suffit.
  • Le reverse proxy mérite une surveillance à part : c’est lui qui rend tout accessible.

Une commande qui ne marche pas, une explication pas claire ? Signaler une erreur dans cette page.

Prêt à vous lancer ?

Choisissez vos applications et récupérez une installation complète.

Créer mon serveur