Le problème que Compose résout
Une vraie application, c’est rarement un seul conteneur. Une API web a besoin d’une base de donnĂ©es, la base de donnĂ©es a besoin d’un volume pour que ses donnĂ©es survivent Ă un redĂ©marrage, puis vous ajoutez un cache Redis et un worker en arrière-plan. Cela fait quatre commandes docker run, chacune avec ses options pour les ports, les volumes, les variables d’environnement et un rĂ©seau partagĂ©. Dans le bon ordre. Chaque fois que vous vous remettez au travail.
Docker Compose remplace ces commandes par un fichier et une commande. Vous dĂ©crivez les conteneurs et la façon dont ils se connectent dans un fichier nommĂ© compose.yaml, et docker compose up les lance tous. Si vous n’avez jamais utilisĂ© les images ni docker run, commencez par ce qu’est Docker et comment fonctionnent les conteneurs.
Ce que décrit le fichier compose
Un fichier compose comporte une poignée de clés de premier niveau. Celle que vous utilisez toujours est services : chaque service est un conteneur que Compose va exécuter.
| |
Deux conteneurs. api est construit Ă partir du Dockerfile du rĂ©pertoire courant et publie le port 8000. db exĂ©cute l’image officielle postgres:18 et conserve ses donnĂ©es dans un volume nommĂ©, si bien que les donnĂ©es sont toujours prĂ©sentes lorsque le conteneur est recréé.
Deux détails font le vrai travail ici :
apiatteintdbvia le nom d’hĂ´tedb. Compose place chaque service sur un rĂ©seau partagĂ© et enregistre le nom de chaque service comme nom DNS. Pas d’adresses IP, pas de--linkĂ l’ancienne.DATABASE_URLpointe versdb:5432et Compose rĂ©sout le nom.depends_onaveccondition: service_healthyretientapijusqu’Ă ce que Postgres rĂ©ponde vraiment. Undepends_onsimple attend seulement que le conteneur dĂ©marre, pas que le processus de base de donnĂ©es Ă l’intĂ©rieur accepte les connexions : cet Ă©cart est la cause la plus frĂ©quente d’un « connection refused » au premier dĂ©marrage.
Les trois clés principales : services, volumes, networks
Trois clés de premier niveau correspondent à des concepts Docker que vous connaissez déjà :
| ClĂ© | Ce qu’elle dĂ©finit | L’Ă©quivalent Ă la main |
|---|---|---|
services | les conteneurs à exécuter | docker run |
volumes | des volumes nommés pour les données qui doivent persister | docker volume create |
networks | des réseaux entre services | docker network create |
networks, vous le dĂ©clarez rarement. Compose crĂ©e un rĂ©seau par projet et y rattache chaque service. VoilĂ pourquoi l’exemple avec Postgres n’a demandĂ© aucune configuration rĂ©seau. Ne dĂ©clarez des rĂ©seaux explicitement que lorsque vous voulez empĂŞcher des groupes de services de s’atteindre :
| |
Les commandes que vous utiliserez vraiment
Exécutez-les depuis le répertoire qui contient compose.yaml.
| |
up et down sont le duo que vous tapez le plus. Vous pouvez relancer up sans risque : après une modification du fichier, il ne recrée que les services dont la configuration a changé et laisse les autres tranquilles.
Ce que docker compose up affiche au premier lancement
Lancez l’exemple avec Postgres ci-dessus et vous obtenez Ă peu près ceci :
| |
Compose fait prĂ©cĂ©der chaque nom de celui du projet (le rĂ©pertoire, par dĂ©faut) et le fait suivre d’un numĂ©ro, parce qu’il peut lancer plusieurs rĂ©pliques d’un mĂŞme service. app-db-1 passe Ă Healthy avant que app-api-1 dĂ©marre : c’est condition: service_healthy qui fait son travail.
Comment garder les mots de passe hors du fichier compose
Compose lit un fichier nommé .env dans le répertoire du projet et remplace les références ${VAR} dans le fichier compose :
| |
| |
Gardez .env hors du contrĂ´le de version et versionnez Ă la place un .env.example avec des valeurs vides ou factices. Pour tout ce qui est rĂ©ellement sensible dans un environnement dĂ©ployĂ©, utilisez les Docker secrets plutĂ´t que des variables d’environnement.
Services optionnels avec les profiles
Tous les services n’ont pas Ă dĂ©marrer Ă chaque fois. Une entrĂ©e profiles garde un service inactif tant que vous ne le demandez pas :
| |
docker compose up démarre api et db et ignore complètement seed. docker compose --profile tools run --rm seed exécute le seeder quand vous le demandez. Utilisez les profiles pour tout ce qui est ponctuel : seeders, migrations, un shell de débogage, un générateur de charge que vous ne voulez que pendant un test.
Compose v2 vs l’ancien docker-compose
Si un guide vous dit d’exĂ©cuter docker-compose avec un tiret, il est antĂ©rieur Ă 2023. C’Ă©tait la v1, Ă©crite en Python, aujourd’hui en fin de vie. L’outil actuel est docker compose en tant que sous-commande de la CLI Docker ; il est fourni avec Docker Desktop et avec le paquet du plugin Compose pour Docker Engine.
Les anciens fichiers ont souvent cette ligne en tĂŞte :
| |
La clĂ© version n’a aucun effet dans Compose v2. Compose valide selon la Compose Specification actuelle et vous avertit quand la clĂ© est prĂ©sente. Retirez-la et l’avertissement disparaĂ®t.
Le nom de fichier par défaut a changé lui aussi : compose.yaml est le nom actuel, docker-compose.yml fonctionne encore, et Compose accepte les deux.
Rechargement à chaud pendant le développement
docker compose watch (Compose 2.22 et suivants) met à jour les conteneurs pendant que vous éditez. Ajoutez un bloc develop au service :
| |
sync copie les fichiers modifiĂ©s directement dans le conteneur en cours d’exĂ©cution, donc une modification de code est prise en compte sans reconstruction. rebuild dĂ©clenche une reconstruction complète de l’image quand un fichier qui influe sur le build change, comme un fichier de verrouillage des dĂ©pendances. Lancez-le avec docker compose watch, ou ajoutez --watch Ă up.
Quand Compose est le mauvais outil
Compose exĂ©cute des conteneurs sur une seule machine. C’est lĂ que Compose s’arrĂŞte, et l’essentiel de ce qui lui manque se trouve juste après.
Il convient au développement local, aux tests automatisés en CI et aux petits déploiements sur un seul hôte. Il ne sait pas planifier des conteneurs sur plusieurs serveurs, en remplacer un quand un nœud tombe, faire des déploiements progressifs conditionnés aux healthchecks, ni autoscaler.
C’est le travail d’un orchestrateur : Kubernetes, ou Docker Swarm si vous voulez plus lĂ©ger. Les deux ne sont pas en concurrence. Un fichier compose est souvent le brouillon qui devient ensuite un jeu de manifestes Kubernetes, et beaucoup d’Ă©quipes continuent d’utiliser Compose en local longtemps après que la production est passĂ©e sur un cluster.
Podman n’est pas en reste : podman compose et podman-compose lisent le mĂŞme format de fichier, avec les rĂ©serves dĂ©taillĂ©es dans Docker vs Podman.
Erreurs courantes
- Des secrets versionnés dans
compose.yaml. Le fichier finit dans Git. Utilisez.env(dans gitignore) ou Docker secrets. - Se fier Ă
depends_onpour attendre qu’un service soit prĂŞt. Seul, il attend que le conteneur dĂ©marre, pas que le service accepte les connexions. Associez-le Ă unhealthchecketcondition: service_healthy. - DĂ©finir
container_name. Cela vous empĂŞche d’exĂ©cuter plusieurs copies du projet et cassedocker compose up --scale. Laissez Compose nommer les conteneurs. - Faire un bind mount par-dessus un rĂ©pertoire de dĂ©pendances installĂ©es. Monter le dossier du projet dans un conteneur Node ou Python peut masquer le
node_modulesou le virtualenv créé pendant le build. Montez des sous-dossiers du code source, ou placez un volume anonyme sur le chemin des dépendances.
Comment faire passer une application existante sur Compose
Prenez l’application que vous dĂ©marrez aujourd’hui avec un script plein de lignes docker run et faites-la passer dans un compose.yaml, un service Ă la fois. Lancez-la, lisez les logs, corrigez ce qui casse, ajoutez le service suivant. Donnez un healthcheck Ă tout ce dont d’autres services dĂ©pendent : c’est l’Ă©tape qu’on saute, et c’est celle qui arrĂŞte le « connection refused » au dĂ©marrage Ă froid.
Vous saurez que c’est bon quand docker compose down -v && docker compose up reconstruit tout l’environnement Ă partir de rien et que l’application revient Ă l’identique Ă chaque fois.