Ce qu’il faut retenir
- Le script automatise l’arrêt complet des containers puis leur redémarrage dans un ordre défini : d’abord les services critiques (Nginx Proxy Manager, MariaDB, Apache), ensuite les applications métier.
- Il sépare les conteneurs en deux tableaux (
PRIORITY_CONTAINERSetADDITIONAL_CONTAINERS) pour garantir que les services d’infrastructure sont opérationnels avant de lancer les containers secondaires, contournant ainsi les limites dedepends_on. - Cette approche ne modifie aucun
docker‑compose.ymlexistant, est facilement personnalisable (chemins, temps d’attente, variables d’environnement) et peut être installée comme commande globale dans~/.local/binpour une utilisation quotidienne fluide.
Résumé généré par IA
Quand on travaille sur plusieurs projets Docker en parallèle, la gestion du démarrage des containers peut vite devenir un casse-tête. Imaginons un environnement de développement typique : un Nginx Proxy Manager qui gère vos entrées HTTP, une base de données MariaDB partagée, et plusieurs applications web indépendantes. Chaque projet a son propre docker-compose.yml, ce qui est une bonne pratique pour maintenir une séparation claire des responsabilités. Mais comment s’assurer que tout démarre dans le bon ordre ?
La problématique
Vous connaissez probablement ce scénario :
- Vous démarrez votre Nginx Proxy Manager… mais attendez, il y a déjà des containers qui tournent
- Vous arrêtez tout, redémarrez dans ce qui vous semble être le bon ordre
- Une application plante parce que la base de données n’était pas prête
- Vous recommencez…
Docker Compose propose bien l’option depends_on, mais elle présente deux limitations majeures :
- Elle ne fonctionne qu’au sein d’un même fichier docker-compose.yml
- Elle ne garantit pas que les services sont réellement « prêts », juste qu’ils ont démarré
Une solution pragmatique
Et si on pouvait simplement avoir un script qui :
- Arrête proprement tous les containers en cours
- Redémarre chaque projet dans un ordre précis
- Attend le bon moment avant de passer au suivant
- Gère aussi bien les services critiques que les applications secondaires
C’est exactement ce que nous allons mettre en place avec un script Bash simple mais efficace. L’idée est de définir deux catégories de containers :
- Les containers prioritaires (infrastructure critique)
- Les containers additionnels (applications métier)
Pourquoi cette approche ?
Cette solution présente plusieurs avantages :
- Pas besoin de modifier vos docker-compose.yml existants
- Contrôle total sur l’ordre de démarrage
- Facilement adaptable à vos besoins
- Idéal pour les environnements de développement
- Fonctionne avec n’importe quelle structure de projets
Dans la suite de cet article, nous allons voir en détail comment implémenter cette solution, la personnaliser selon vos besoins, et l’utiliser efficacement dans votre workflow quotidien.
La mise en place du script
Notre script va s’articuler autour d’une structure simple mais efficace. Commençons par la base :
#!/bin/bash # Description: Script pour arrêter et redémarrer les containers Docker dans un ordre spécifique
1. Configuration des priorités
La première étape consiste à définir nos containers par ordre de priorité. Nous utilisons deux tableaux pour une meilleure organisation :
# Définition des chemins de base des containers prioritaires
PRIORITY_CONTAINERS=(
"/Users/samy/Sites/docker/containers/Nginx-Proxy-Manager"
"/Users/samy/Sites/docker/containers/mariadb"
"/Users/samy/Sites/docker/containers/www/apache_php8"
)
# Tableau pour les containers additionnels
ADDITIONAL_CONTAINERS=(
"/Users/samy/Sites/docker/containers/laravel_test"
"/Users/samy/Sites/Projects/blog"
"/Users/samy/Sites/Projects/Laravel"
)
Pourquoi cette séparation ?
La distinction entre containers prioritaires et additionnels n’est pas qu’esthétique :
- Les containers prioritaires sont généralement des services d’infrastructure
- Ils doivent être pleinement opérationnels avant le démarrage des autres services
- Cette séparation permet une maintenance plus claire
- Facilite l’ajout ou la suppression de projets
Le choix des containers prioritaires est personnel et dépend entièrement de ton contexte. Dans mon cas, on a NPM, mariadb et apache. De ton côté, tu pourrais avoir un traefik, postgresql etc.
2. Les fonctions utilitaires
Nous avons besoin de deux fonctions principales :
# Fonction pour arrêter tous les containers
stop_all_containers() {
echo "Arrêt de tous les containers Docker..."
docker stop $(docker ps -q) 2>/dev/null
docker rm $(docker ps -aq) 2>/dev/null
sleep 2
}
# Fonction pour démarrer un container
start_container() {
local container_path="$1"
if [ -d "$container_path" ]; then
echo "Démarrage du container dans: $container_path"
cd "$container_path" && docker compose up -d
# Attente pour s'assurer que le container est bien démarré
sleep 5
else
echo "ERREUR: Le répertoire $container_path n'existe pas"
fi
}
Zoom sur stop_all_containers()
- docker stop $(docker ps -q) arrête tous les containers en cours d’exécution
- docker rm $(docker ps -aq) supprime les containers arrêtés
- La redirection 2>/dev/null évite les messages d’erreur si aucun container n’est présent
- Le sleep 2 assure que tout est bien arrêté avant de continuer
Analyse de start_container()
- Vérifie l’existence du répertoire avant toute action
- Utilise cd pour se placer dans le bon contexte
- Lance le container avec docker compose up -d
- Le sleep 5 est crucial pour laisser le temps au container de démarrer
L’instruction sleep 5 permet d’introduire une pause de 5 secondes entre le démarrage des containers. Cette temporisation assure un démarrage séquentiel et stable de l’environnement. Dans mon cas, après plusieurs tests, 5 secondes se sont avérées suffisantes pour mes containers. Cependant, ce délai est à ajuster selon vos besoins et la complexité de vos services.
3. La fonction principale
Le cœur du script qui orchestre tout :
main() {
# 1. Arrêt de tous les containers
stop_all_containers
# 2. Démarrage des containers prioritaires dans l'ordre
echo "Démarrage des containers prioritaires..."
for container in "${PRIORITY_CONTAINERS[@]}"; do
start_container "$container"
done
# 3. Démarrage des containers additionnels
if [ ${#ADDITIONAL_CONTAINERS[@]} -gt 0 ]; then
echo "Démarrage des containers additionnels..."
for container in "${ADDITIONAL_CONTAINERS[@]}"; do
start_container "$container"
done
fi
echo "Opération terminée!"
}
# Exécution du script
main
Points clés à noter
- Ordre d’exécution :
- Arrêt propre de l’existant
- Démarrage séquentiel des prioritaires
- Puis démarrage des additionnels
- Gestion des erreurs :
- Vérification de l’existence des répertoires
- Redirection des erreurs pour les commandes sensibles
- Messages clairs pour le suivi
- Temps d’attente :
- Entre l’arrêt et le redémarrage
- Après chaque démarrage de container
- Ajustables selon vos besoins
Personnalisation et bonnes pratiques
1. Adapter le script à votre environnement
Le script peut être facilement personnalisé selon vos besoins. Voici les principaux points d’adaptation :
# Variables d'environnement personnalisables
BASE_PATH="/Users/samy/Sites/docker/containers"
WAIT_AFTER_STOP=2 # Temps d'attente après l'arrêt (en secondes)
WAIT_AFTER_START=5 # Temps d'attente après chaque démarrage
# Version améliorée des tableaux de containers
PRIORITY_CONTAINERS=(
"${BASE_PATH}/Nginx-Proxy-Manager" # Proxy - démarre en premier
"${BASE_PATH}/mariadb" # Base de données
"${BASE_PATH}/www/apache_php8" # Serveur web
)
Cette configuration part du principe que tous vos containers sont centralisés au même endroit. Si ce n’est pas le cas, vous devrez définir plusieurs variables source pour chaque emplacement. Dans mon cas par exemple, j’utilise deux répertoires distincts :
- /Users/samy/Sites/docker/containers : dédié aux containers temporaires, de test, ou indépendants des projets
- /Users/samy/Sites/projects : comme son nom l’indique, réservé aux containers liés aux projets en cours
2. Amélioration de la gestion des temps d’attente
Une version plus sophistiquée de la fonction start_container pourrait inclure des temps d’attente personnalisés :
start_container() {
local container_path="$1"
local wait_time="${2:-$WAIT_AFTER_START}" # Utilise la valeur par défaut si non spécifiée
if [ -d "$container_path" ]; then
echo "🚀 Démarrage du container dans: $container_path"
cd "$container_path" && docker compose up -d
echo "⏳ Attente de $wait_time secondes pour stabilisation..."
sleep $wait_time
echo "✅ Démarrage terminé pour: $container_path"
else
echo "❌ ERREUR: Le répertoire $container_path n'existe pas"
return 1
fi
}
Ce ne sont que deux exemples d’améliorations possibles, mais les possibilités sont nombreuses. Voici quelques suggestions :
- Implémenter un contrôle post-démarrage pour vérifier l’état des containers
docker ps | grep -q "$container_name" # Retourne true/false selon l'état du container
- Enrichir le système de logs pour plus de détails sur le démarrage
- Et bien d’autres optimisations possibles comme :
- Gestion des dépendances entre containers
- Monitoring des ressources
- Alertes en cas d’échec
- Redémarrage automatique sur erreur
💡 L’objectif est d’automatiser au maximum pour un environnement plus robuste et facile à maintenir.
Bonnes pratiques d’utilisation
Placement du script
Concernant le placement du script, je le traite comme une commande système en le plaçant dans ~/.local/bin/. Cette approche présente plusieurs avantages :
- Le script devient disponible globalement dans le système
- Accessible depuis n’importe quel répertoire
chmod +x restart-containers.sh mv restart-containers.sh ~/.local/bin/reloadDockerContainer
⚠️ Points importants à noter :
- Le script doit être marqué comme exécutable (chmod +x)
- L’utilisation de chemins absolus est cruciale (comme expliqué précédemment)
- Le répertoire ~/.local/bin/ doit être dans votre
$PATH
💡 Pro tip : Cette organisation permet de gérer le script comme une véritable commande système, facilitant son utilisation quotidienne
Alias utile
Pour simplifier encore plus l’utilisation, je recommande la création d’un alias. Cette approche offre deux avantages majeurs :
- Organisation plus claire :
- Tu peux nommer ton script de façon explicite (ex: restart-containers.sh)
- Distinction facile entre les commandes système et tes scripts personnels
- Utilisation simplifiée :
- Commande courte et mémorisable
- Accessible partout dans le système
Pour configurer l’alias, ajoute cette ligne dans ton ~/.bashrc ou ~/.zshrc :
alias rdocker='reloadDockerContainer'
🚀 TL;DR : Pour les Ninjas du Ctrl+C/Ctrl+V
Ah, je vous vois venir, vous les as du copier-coller, qui surfez sur Stack Overflow (Bon, OK, maintenant avec les LLM, c’est beaucoup moins utilisé) plus vite que votre ombre ! Vous savez, ceux qui lisent le dernier chapitre d’un livre policier en premier… 😏
#!/bin/bash
# Description: Script pour arrêter et redémarrer les containers Docker dans un ordre spécifique
# Définition des chemins de base des containers prioritaires
PRIORITY_CONTAINERS=(
"/Users/samy/Sites/docker/containers/Nginx-Proxy-Manager"
"/Users/samy/Sites/docker/containers/mariadb"
"/Users/samy/Sites/docker/containers/www/apache_php8"
# ICI les autres
)
# Tableau pour les containers additionnels (à remplir selon vos besoins)
ADDITIONAL_CONTAINERS=(
"/Users/samy/Sites/docker/containers/laravel_test"
"/Users/samy/Sites/projets/blog"
# Ajoutez vos containers supplémentaires ici, exemple:
# "/Users/samy/Sites/docker/containers/container1"
# "/Users/samy/Sites/docker/containers/container2"
)
# Fonction pour arrêter tous les containers
stop_all_containers() {
echo "Arrêt de tous les containers Docker..."
docker stop $(docker ps -q) 2>/dev/null
docker rm $(docker ps -aq) 2>/dev/null
sleep 2
}
# Fonction pour démarrer un container
start_container() {
local container_path="$1"
if [ -d "$container_path" ]; then
echo "Démarrage du container dans: $container_path"
cd "$container_path" && docker compose up -d
# Attente pour s'assurer que le container est bien démarré
sleep 5
else
echo "ERREUR: Le répertoire $container_path n'existe pas"
fi
}
# Fonction principale
main() {
# 1. Arrêt de tous les containers
stop_all_containers
# 2. Démarrage des containers prioritaires dans l'ordre
echo "Démarrage des containers prioritaires..."
for container in "${PRIORITY_CONTAINERS[@]}"; do
start_container "$container"
done
# 3. Démarrage des containers additionnels
if [ ${#ADDITIONAL_CONTAINERS[@]} -gt 0 ]; then
echo "Démarrage des containers additionnels..."
for container in "${ADDITIONAL_CONTAINERS[@]}"; do
start_container "$container"
done
fi
echo "Opération terminée!"
}
# Exécution du script
main
Voilà, vous pouvez maintenant partir en courant avec ce code sous le bras, tel Indiana Jones s’échappant avec un artéfact précieux ! Mais n’oubliez pas : comprendre ce que vous copiez-collez, c’est comme lire les instructions IKEA avant de monter un meuble… Ça peut parfois éviter des surprises ! 🎪
PS : Si votre container crashe, on ne se connaît pas… ! Lisez l’article complet, il y a des trucs cool dedans, promis ! 🤓

