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.
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é
- À 4 h, la mise à jour automatique du système trouve une nouvelle version de
docker-ceetcontainerd. - L’installation redémarre le service Docker, qui arrête proprement tous les conteneurs.
- Docker redémarre et relance les conteneurs marqués
restart: unless-stopped. - 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 dockerne 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.