Docker Compose : aide-mémoire pour serveurs
Retrouvez les commandes Compose V2 par tâche : cycle de vie, changements, logs, shells, réseaux, volumes et nettoyage sûr, avec les pièges courants.
Les commandes Compose que vous utiliserez réellement
Docker Compose fournit des dizaines de sous-commandes. Au quotidien, l’administration d’un serveur en utilise environ une douzaine. Cette page les regroupe selon l’opération effectuée, donne une raison simple pour chacune et renvoie vers l’explication détaillée lorsqu’une commande présente un piège.
Tout ce qui suit utilise Compose V2 ou V5 : docker compose avec un espace, et non l’ancien script docker-compose. Les deux sont des plugins Go. Sous Linux, le plugin Compose s’installe séparément de Docker Engine. Ubuntu 24.04 LTS propose encore l’ancien outil Python V1 sous la forme de docker-compose version 1.29.2-6ubuntu1 dans son dépôt universe. Vérifiez avec docker compose version. Si la commande est indisponible, configurez le dépôt Docker et installez le paquet docker-compose-plugin.
Toutes les commandes ci-dessous s’exécutent depuis le répertoire qui contient votre fichier compose.yaml. Par défaut, Compose utilise le nom de ce répertoire comme nom du projet, sauf si vous le remplacez. Sans -f ni COMPOSE_FILE, Compose recherche un fichier de configuration dans le répertoire de travail et ses répertoires parents. Ainsi, une exécution depuis le répertoire parent ne trouve votre stack que si son fichier se trouve encore dans ce chemin de recherche. Si le format du fichier vous est encore inconnu, commencez par un premier fichier Compose sur un VPS, puis revenez ici pour les commandes.
Cycle de vie : les quatre commandes que vous saisissez et celle qui supprime les conteneurs
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d crée le réseau, crée les conteneurs, les démarre, puis rend la main. La commande rend la main après le démarrage des conteneurs, sans attendre que les applications soient prêtes. C’est pourquoi un script de déploiement qui lance ensuite une vérification curl échoue souvent au premier essai. up -d --wait attend que les services dotés de healthchecks deviennent sains et que les services qui en sont dépourvus soient démarrés ; un service non sain ou l’expiration d’un --wait-timeout entraîne une sortie avec un code différent de zéro. Ce flag n’est fiable que si la vérification sous-jacente l’est aussi. Écrivez donc un healthcheck que Compose peut utiliser avant de vous appuyer dessus dans l’automatisation.
stop arrête les conteneurs et les conserve. start redémarre donc les mêmes conteneurs avec la même couche inscriptible. down les arrête, puis supprime les conteneurs et le réseau du projet. Tout ce qui a été écrit dans le conteneur, en dehors d’un volume, est supprimé avec lui. C’est le malentendu le plus coûteux dans Compose. La différence complète entre down et stop explique les conséquences concrètes.
restart n’est pas un reload. La commande arrête puis redémarre le même conteneur avec la configuration qu’il possède déjà. Une variable d’environnement modifiée, un nouveau tag d’image ou une modification du mapping de port n’a donc aucun effet. Pour appliquer une modification du fichier, vous devez relancer up -d. Compose compare chaque service à son conteneur en cours d’exécution et recrée ceux dont la configuration ou l’image a changé.
Appliquer une modification : recréer, télécharger ou reconstruire
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webup -d réutilise les conteneurs en cours d’exécution lorsque leur configuration et leur image sont inchangées ; le téléchargement et la compilation des images suivent la pull policy du service. --force-recreate ignore cette comparaison et remplace chaque conteneur, même lorsque la configuration est identique. C’est donc le moyen le plus rapide de supprimer un état incohérent dans un conteneur.
La procédure explicite de mise à jour d’une image utilise deux commandes, car elles ont deux fonctions différentes. pull télécharge l’image actuelle correspondant à chaque tag indiqué dans le fichier. up -d constate ensuite que l’ID de l’image du service ne correspond plus à celui du conteneur en cours d’exécution et le recrée. Avec la pull policy missing par défaut, les tags mis en cache sont réutilisés, sauf latest, qui est toujours téléchargé. Le risque inverse apparaît avec une stack comprenant plusieurs services : télécharger latest pour tous les services en même temps peut interrompre une application qui fonctionnait encore dix secondes plus tôt. C’est pourquoi un espace de travail AFFiNE auto-hébergé recommande plutôt d’épingler l’image de l’application et celle de la migration sur le même digest. L’épinglage transforme également une mise à niveau en une modification volontaire du tag, suivie du même téléchargement et de la même recréation. Avec une stack qui migre sa base de données au démarrage, vous devez disposer d’un dump avant d’exécuter l’une ou l’autre commande. C’est la procédure que suit un centre de support Chatwoot auto-hébergé pour chaque mise à niveau de version.
build s’applique aux services qui déclarent une section build:, y compris ceux qui déclarent également une section image:. up -d --build construit et démarre en une seule étape. C’est la boucle normale lorsque vous modifiez le code. Utilisez --no-cache uniquement lorsqu’une couche mise en cache est manifestement obsolète, car cette commande reconstruit chaque couche depuis zéro. Certains projets proposent les deux méthodes à partir d’un même dépôt cloné. Les deux boucles sont alors des chemins de mise à jour différents : un suivi d’entraînement openGym auto-hébergé utilise docker compose up -d --build pour construire son checkout épinglé, car télécharger ses images latest peut exécuter une version plus récente que celle de ce checkout.
Voir ce qui s’exécute
docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose lsps liste uniquement les conteneurs en cours d’exécution. Un service qui s’est arrêté pendant son démarrage est invisible dans cette liste tant que vous n’ajoutez pas -a. Ainsi, un conteneur absent de ps alors que ps -a l’affiche comme Exited (1) correspond au cas habituel d’un échec au démarrage. Consultez le code de sortie, puis les journaux.
logs -f suit tous les services simultanément et préfixe chaque ligne avec le nom du service. C’est la vue à utiliser lorsque les services communiquent entre eux et que l’ordre des événements est important. Indiquez le nom d’un service pour limiter l’affichage. --tail=100 est utile pour un conteneur actif depuis un mois, car l’affichage par défaut montre tout l’historique et surcharge le terminal. --since 15m répond généralement à la question que vous vous posez : que s’est-il passé pendant le redémarrage que vous venez d’effectuer ?
top liste les processus présents dans chaque conteneur. Cela permet de distinguer « le conteneur est en cours d’exécution » de « le processus à l’intérieur du conteneur est en cours d’exécution ». ls sort du répertoire courant et liste sur l’hôte les projets Compose en cours d’exécution, avec leur état ; ajoutez -a pour inclure les projets arrêtés.
Ouvrir un shell dans un service
docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web shexec exécute une commande dans un conteneur déjà démarré. run démarre un nouveau conteneur à partir de la même définition de service. C’est nécessaire lorsque le service ne reste pas actif assez longtemps pour permettre l’utilisation de exec. Associez toujours run à --rm. Sans cette option, chaque appel laisse derrière lui un conteneur arrêté. Ces conteneurs s’accumulent jusqu’à rendre docker compose ps -a illisible.
Essayez sh avant bash. Certaines images basées sur Alpine incluent bash, notamment l’image Alpine officielle de PostgreSQL. Lorsqu’il est absent, l’échec affiche exec: "bash": executable file not found in $PATH. Ajouter --no-deps à run ignore les dépendances du service. Cela évite qu’une simple vérification rapide de la configuration ne démarre toute votre base de données.
run --rm web env est le moyen le plus rapide de voir l’environnement réellement transmis à un service, après la fusion de chaque fichier .env, bloc environment: et variable shell. Lorsqu’une valeur est incorrecte, l’ordre de fusion en est généralement la cause. la manière dont Compose résout les fichiers env et les secrets précise quelle source est prioritaire.
Réseaux, ports et résolution de noms
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksPar défaut, Compose place tous les services sur un même réseau de projet, et le nom de chaque service devient un nom DNS sur ce réseau. Exécuter getent hosts db dans web, lorsque l’image inclut getent, vérifie la résolution de noms ; cela ne teste pas si db accepte les connexions. Si le nom est résolu mais que la connexion est refusée, vérifiez que le serveur fonctionne et écoute sur l’adresse et le port demandés ; une écoute limitée à 127.0.0.1 est une cause possible. La même limite explique pourquoi un conteneur démarré en dehors du projet, avec docker run ou dans sa propre stack, a besoin d’un réseau partagé pour résoudre un nom de service comme jellyfin. C’est le premier point à vérifier lorsqu’une interface frontale Halcyon pour votre bibliothèque Jellyfin ne peut pas joindre le serveur qu’elle cible. Le reste de ce modèle est expliqué dans le fonctionnement des réseaux Compose et du DNS des services.
port web 80 affiche l’adresse de l’hôte et le port sur lesquels un port de conteneur est publié. Cela évite de devoir deviner lorsque le mapping provient d’une variable. La publication d’un port crée également une règle de pare-feu que Docker gère lui-même. Cette règle passe avant les vôtres. Un service que vous pensiez privé peut donc être accessible depuis Internet. Ce cas est expliqué dans pourquoi les ports Docker publiés contournent ufw. Il est plus sûr de laisser ces ports non publiés et de placer à la place un proxy qui authentifie les requêtes sur le réseau du projet, devant les services. C’est ce que permet l’exécution d’Authentik comme couche d’authentification unique.
Volumes et données
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes affiche les volumes nommés déclarés par le projet, un par ligne. Cette liste ne constitue qu’une partie de l’inventaire des sauvegardes : les bind mounts et les fichiers de configuration doivent également être vérifiés. Lorsque les volumes contiennent des données irremplaçables, la commande de sauvegarde exacte est aussi importante que la liste. C’est pourquoi la comparaison entre PhotoPrism et Immich détaille les commandes de dump et de copie nécessaires pour chaque serveur photo. cp copie un fichier vers ou depuis un conteneur sans ouvrir de shell, en utilisant la forme service:path du côté où se trouve le conteneur.
down -v supprime les volumes nommés déclarés, à l’exception des volumes externes, ainsi que les volumes anonymes attachés aux conteneurs, en même temps que les conteneurs. Cette commande convient pour supprimer une stack de test, mais pas pour quoi que ce soit qui contient des données importantes, car aucune confirmation n’est demandée et aucune annulation n’est possible. Les bind mounts y survivent, puisqu’ils résident dans le système de fichiers de l’hôte. Cette différence de portée des effets destructeurs explique notamment pourquoi il faut choisir délibérément entre les bind mounts et les volumes nommés.
Nettoyage pour libérer de l’espace disque sans perdre de données
docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune--remove-orphans supprime les conteneurs qui appartiennent au projet, mais qui n’apparaissent plus dans le fichier. C’est exactement ce qui se produit après avoir renommé un service. Sans cette commande, ces conteneurs continuent de fonctionner, et docker compose ps inclut par défaut les conteneurs orphelins en cours d’exécution.
docker system df indique où l’espace disque est utilisé avant toute suppression. La commande distingue les images, les conteneurs, les volumes locaux et le cache de build, avec une estimation de l’espace récupérable pour chacun. image prune -a supprime toutes les images qu’aucun conteneur n’utilise, qu’elles soient taguées ou non. Sur une machine qui a téléchargé plusieurs versions d’une image volumineuse, c’est généralement le nettoyage le plus rentable. builder prune supprime par défaut le cache de build dangling ; ajoutez -a pour supprimer tout le cache de build inutilisé.
Aucune de ces commandes ne touche aux volumes nommés. docker volume prune --all, docker compose down -v et docker volume rm suppriment les volumes nommés. docker volume prune seul supprime uniquement les volumes anonymes.
Vérifier le fichier avant qu’il ne provoque un problème
docker compose config --quiet
docker compose config --services
docker compose --dry-run up -dconfig --quiet valide le fichier et n’affiche rien en cas de succès. Il convient donc à une étape de pré-déploiement ou à un hook Git. config affiche le fichier entièrement fusionné et interpolé. Cela permet de vérifier qu’une variable a bien été résolue et qu’un fichier d’override a été appliqué comme prévu. Une variable non définie apparaît alors avec une valeur vide, accompagnée de l’avertissement The "X" variable is not set. Defaulting to a blank string.
--dry-run est une option globale, et non une option de sous-commande. Elle doit donc être placée avant up. Cette commande affiche toutes les actions que Compose effectuerait sans rien modifier. Ces trente secondes sont utiles avant un down sur une stack importante.
Utiliser plusieurs fichiers, profils et projets
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -dPlusieurs options -f sont fusionnées dans l’ordre, et les fichiers suivants remplacent les valeurs des fichiers précédents clé par clé. C’est la méthode standard pour conserver un fichier de base avec une petite surcharge de configuration pour la production. Les règles diffèrent toutefois pour les listes et les maps. Consultez donc la fusion de plusieurs fichiers Compose avant de rechercher la cause d’un comportement inattendu.
--profile démarre les services associés à ce profil en plus de ceux qui ne sont associés à aucun profil. Les outils de débogage restent ainsi exclus d’un up normal. -p définit le nom du projet. Deux copies d’une même stack peuvent donc fonctionner côte à côte avec des réseaux et des noms de volumes distincts. Pour relancer la stack après un redémarrage, utilisez une restart policy ou une unité qui exécute Compose. Cette méthode est décrite dans démarrer des stacks Compose au boot.
FAQ
Qu’est-ce qui a remplacé docker-compose avec un espace ?
Compose V2 et V5, appelés avec docker compose et un espace. Sous Linux, Compose est un plugin installé séparément ; Ubuntu 24.04 LTS propose encore l’outil Python V1 dans son dépôt universe. Si la forme avec espace n’est pas disponible, configurez le dépôt Docker et installez le paquet docker-compose-plugin. Mettez à jour les anciens scripts pour utiliser la forme avec espace au lieu d’ajouter un alias, car V2 possède des options que V1 n’avait pas.
Pourquoi docker compose restart ne prend-il pas en compte ma modification de configuration ?
restart arrête puis redémarre le conteneur existant avec la configuration utilisée lors de sa création. Il ne relit jamais compose.yaml. Toute modification des variables d’environnement, des ports, des volumes ou du tag d’image nécessite docker compose up -d. Cette commande compare chaque service à son conteneur en cours d’exécution et recrée ceux qui diffèrent. Ajoutez --force-recreate pour forcer le remplacement même si aucun élément du fichier n’a changé.
Comment mettre à jour un service vers une image plus récente ?
Exécutez docker compose pull, puis docker compose up -d. La commande pull récupère l’image actuelle pour chaque tag présent dans le fichier. up -d recrée ensuite les services dont l’identifiant d’image ne correspond plus à celui de leur conteneur. L’exécution de up -d seule suit la pull policy : la policy missing par défaut réutilise les images en cache, sauf pour latest, qui est toujours récupérée.
Quelles commandes de nettoyage sont sûres sur un serveur en production ?
docker system df indique l’utilisation de l’espace disque sans rien supprimer. docker image prune -a et docker builder prune suppriment les images inutilisées et le build cache ; les services en cours d’exécution continuent donc de fonctionner et les volumes nommés restent intacts. La paire dangereuse est docker compose down -v. Elle supprime sans confirmation les volumes nommés non externes déclarés par le projet ainsi que les volumes anonymes attachés. docker volume prune --all supprime les volumes locaux inutilisés, y compris les volumes nommés, après une seule demande de confirmation y/N, ou sans aucune demande avec -f. Exécutez d’abord docker compose config --volumes pour connaître les éléments susceptibles d’être supprimés.
Puis-je exécuter une seule commande sans démarrer toute la stack ?
Oui. docker compose run --rm --no-deps web sh démarre un seul conteneur à partir de la définition du service web, ignore ses dépendances et supprime le conteneur lorsque vous quittez. Utilisez plutôt exec lorsque le conteneur est déjà en cours d’exécution, car exec exécute votre commande dans le conteneur actif et vous montre l’état réel du service.