Aller au contenu

Introduction à Docker Compose

Mise à jour :

logo docker-compose

Docker Compose est un outil puissant permettant de définir et de gérer des applications conteneurisées multi-services en utilisant un simple fichier YAML. Il simplifie l’orchestration des conteneurs Docker en automatisant leur création, leur configuration et leur mise en réseau. Grâce à Docker Compose, il est possible de déployer et de maintenir des environnements complexes avec un minimum d’effort, tout en garantissant la reproductibilité et la portabilité des configurations. Ce guide explore les fonctionnalités essentielles de Docker Compose, de son installation à la gestion avancée des réseaux et des volumes.

Concepts de base

Docker Compose repose sur plusieurs objets fondamentaux pour orchestrer des applications conteneurisées :

  • Services : Un service correspond à un conteneur Docker défini dans le fichier YAML. Chaque service décrit un aspect de l’application, comme une base de données, une API, ou une interface utilisateur.
  • Volumes : Les volumes sont des espaces de stockage partagés entre conteneurs pour persister les données au-delà du cycle de vie des conteneurs.
  • Réseaux : Les réseaux permettent aux services de communiquer entre eux. Docker Compose crée automatiquement un réseau par défaut, mais il est aussi possible de configurer des réseaux personnalisés.
  • Fichier docker-compose.yml : Ce fichier est le cœur de Docker Compose. Il décrit la configuration des services, les volumes à monter, les réseaux à utiliser et d’autres options de déploiement.

Ces concepts de base sont essentiels pour comprendre et utiliser efficacement Docker Compose dans la gestion d’applications multi-services.

Installation de docker-compose

Terminal window
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt remove $pkg; done
sudo apt update
sudo apt install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

On vérifie :

Terminal window
docker compose --help
Usage: docker compose [OPTIONS] COMMAND
Define and run multi-container applications with Docker.
Options:
--ansi string Control when to print ANSI control characters ("never"|"always"|"auto") (default "auto")
--compatibility Run compose in backward compatibility mode
--dry-run Execute command in dry run mode
--env-file stringArray Specify an alternate environment file.
-f, --file stringArray Compose configuration files
--parallel int Control max parallelism, -1 for unlimited (default -1)
--profile stringArray Specify a profile to enable
--progress string Set type of progress output (auto, tty, plain, quiet) (default "auto")
--project-directory string Specify an alternate working directory
(default: the path of the, first specified, Compose file)
-p, --project-name string Project name
Commands:
build Build or rebuild services
config Parse, resolve and render compose file in canonical format
cp Copy files/folders between a service container and the local filesystem
create Creates containers for a service.
down Stop and remove containers, networks
events Receive real time events from containers.
exec Execute a command in a running container.
images List images used by the created containers
kill Force stop service containers.
logs View output from containers
ls List running compose projects
pause Pause services
port Print the public port for a port binding.
ps List containers
pull Pull service images
push Push service images
restart Restart service containers
rm Removes stopped service containers
run Run a one-off command on a service.
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker Compose version information
wait Block until the first service container stops
Run 'docker compose COMMAND --help' for more information on a command.

Structure d’un fichier Docker Compose

Le fichier docker-compose.yaml définit l’ensemble des services qui composent votre application, ainsi que leurs configurations, les réseaux et les volumes associés. Voici une structure de base d’un fichier Docker Compose :

version: '3' # Version de Docker Compose à utiliser
services:
service1: # Nom du premier service
image: nom_de_l_image # Image Docker utilisée pour ce service
ports:
- "port_hôte:port_conteneur" # Mappage des ports
environment:
- VARIABLE_1=valeur_1 # Variables d'environnement
volumes:
- /chemin/hote:/chemin/conteneur # Mappage de volumes
depends_on:
- service2 # Dépendances entre les services
service2:
# Configuration du deuxième service
# ...
networks:
mynetwork: # Définition d'un réseau personnalisé
driver: bridge # Type de réseau

Configuration des services

Commençons maintenant par inspecter les principaux paramètres d’un service.

Les images

Si l’image dont nous avons besoin pour notre service a déjà été publiée dans une registry, alors nous il utiliser la référence avec l’attribut image :

services:
my-service:
image: ubuntu:latest

Il est aussi possible de créer une image à partir du code d’un fichier Dockerfile, avec le paramètre build. Ce paramètre peut être un chemin ou une Url :

services:
web:
build: /path/to/dockerfile/
...
db:
build: https://gitlab.com/srobert/my-project.git

Il est possible d’ajouter le paramètre image qui taguera l’image une fois créée. Ce qui permet de la rendre disponible pour d’autres services :

services:
web:
build: https://gitlab.com/srobert/my-project.git
image: my-project-image
...

La gestion des dépendances entre services

La directive depends_on permet de définir des dépendances entre les services. Elle spécifie qu’un service donné dépend d’un ou plusieurs autres services avant de pouvoir être démarré. Cela permet de garantir que les services requis sont opérationnels avant de lancer un service dépendant.

L’utilisation de depends_on est particulièrement utile lorsque vous avez une application composée de plusieurs services et que certains d’entre eux ont besoin d’attendre que d’autres services soient prêts avant de pouvoir fonctionner correctement. Voici comment cela fonctionne :

Supposons que vous ayez une application composée de deux services : un service de base de données (par exemple, PostgreSQL) et un service d’application web (par exemple, un serveur Node.js). Le service d’application web dépend de la base de données pour fonctionner correctement.

version: '3'
services:
app:
image: my-node-app
ports:
- "80:80"
depends_on:
- db
db:
image: postgres:latest
environment:
POSTGRES_PASSWORD: mysecretpassword

Dans cet exemple, le service app dépend du service db. Lorsque vous utilisez docker-compose up pour lancer l’ensemble de l’application, Docker Compose veillera à ce que le service db soit démarré en premier, puis seulement le service app sera lancé. Cela garantit que le service d’application web a accès à la base de données dès son démarrage.

Il est important de noter que bien que depends_on permette de gérer l’ordre de démarrage des services, il ne garantit pas que le service dépendant a terminé son initialisation avant de démarrer le service dépendant. Certains services peuvent être prêts à accepter des connexions plus rapidement que d’autres. Pour gérer la synchronisation des dépendances plus avancées, vous devrez peut-être utiliser des outils supplémentaires ou des scripts dans vos conteneurs.

Configuration des réseaux

Les conteneurs Docker communiquent entre eux dans des réseaux créés, implicitement ou via la configuration du même nom.

services:
service-1:
image: alpine:latest
networks:
- network-1
...
service-2:
image: alpine:latest
networks:
- network-1
...
service-3:
image: alpine:latest
networks:
- network-2
...
networks:
network-1: {}
network-2: {}

Vous pouvez spécifier le type de réseau (par exemple, bridge pour un réseau privé), ce qui permet aux services de communiquer entre eux de manière sécurisée.

networks:
network-1: # Définition d'un réseau personnalisé
driver: bridge # Type de réseau

Exposition de ports

Pour atteindre un port d’un conteneur depuis l’hôte, il doit être exposé de manière déclarative via le mot-clé ports :

services:
service-1:
image: alpine:latest
ports:
- "80:80"
...
service-2:
image: alpine:latest
ports:
- "8080:3000"
...
service-3:
image: alpine:latest
ports:
- "8081:3000"
...

Le premier chiffre indique le port sur l’hôte et le second celui du conteneur. Ainsi le port 80 sera visible depuis l’hôte, tandis que le port 3000 des deux autres conteneurs seront disponibles sur les ports 8080 et 8081 de l’hôte. Cela permet d’exécuter différents conteneurs exposant les mêmes ports sans collisions.

Les volumes

La directive volumes permet de configurer des volumes nommés qui peuvent être réutilisés sur plusieurs services. Pour utiliser un volume sur plusieurs services, vous devez explicitement accorder l’accès à chaque service à l’aide de l’attribut volumes.

services:
service-1:
image: alpine:latest
volumes:
- global-volume:/my-volumes/named-global-volume
...
volumes:
global-volume:

Les variables d’environnement

Il est possible de définir des variables d’environnement statiques, ainsi que des variables dynamiques, avec la notation ${} :

services:
database:
image: "postgres:${POSTGRES_VERSION}"
environment:
DB: mydb
USER: "${USER}"

On peut par exemple les définir dans un fichier .env dans le même répertoire.

La gestion des secrets

Dans un environnement DevOps, la gestion des secrets est une préoccupation importante pour garantir la sécurité des données sensibles, telles que les informations d’authentification, les clés API et les autres données confidentielles utilisées par les applications. Docker Compose offre des fonctionnalités pour gérer ces secrets de manière sécurisée. Dans cette partie, nous allons explorer comment Docker Compose permet de gérer les secrets dans un environnement de déploiement.

Création de Secrets

Pour créer un secret dans Docker Compose, vous devez d’abord le définir dans un fichier de configuration. Voici un exemple de définition de secret dans un fichier docker-compose.yml :

version: '3'
services:
myapp:
image: myapp:latest
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret.txt

Dans cet exemple, nous avons défini un service myapp qui utilise un secret nommé my_secret. Le secret est défini en dehors de la section services, sous la section secrets, avec un chemin vers un fichier my_secret.txt qui contient la valeur du secret.

Accès aux Secrets dans les Conteneurs

Les secrets définis dans Docker Compose sont montés dans les conteneurs en tant que fichiers dans le répertoire /run/secrets/. Les conteneurs peuvent y accéder comme s’il s’agissait de fichiers normaux. Par exemple, si vous avez défini un secret nommé my_secret, le conteneur peut le lire depuis /run/secrets/my_secret.

Sécurité des secrets

Les secrets définis dans Docker Compose sont stockés de manière sécurisée sur le système hôte. Ils sont uniquement accessibles par les conteneurs spécifiques qui en ont besoin, ce qui garantit leur confidentialité. De plus, Docker Compose permet de chiffrer les secrets en transit entre les services, renforçant ainsi la sécurité de l’ensemble du processus.

Les commandes de la CLI

Examinons maintenant de plus près la syntaxe de Docker Compose :

Terminal window
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]

Bien qu’il existe de nombreuses options et commandes disponibles, nous devons au moins connaître celles qui permettent de lancer et d’arrêter les services.

Premier lancement

Pour démarrer les conteneurs, les réseaux et les volumes définis dans la configuration, on utilise l’option up :

Terminal window
docker-compose up

Si le fichier de configuration a un nom différent de celui par défaut, docker-compose.yml, vous pouvez utiliser l’option -f avec le nom du fichier :

Terminal window
docker-compose -f custom-compose-file.yml up

On peut aussi demander à docker compose de s’exécuter en arrière-plan en tant que démon avec l’option -d :

Terminal window
docker-compose up -d

Stop

Pour arrêter les services actifs en toute sécurité, nous pouvons utiliser stop, qui préservera les conteneurs, les volumes et les réseaux, ainsi que toutes les modifications qui leur sont apportées :

Terminal window
docker-compose stop

Start

Cependant, après la première fois, nous pouvons simplement utiliser start pour démarrer les services :

Terminal window
docker-compose start

Arrêt et nettoyage

Pour réinitialiser le statut de notre projet, nous pouvons simplement utiliser la commande down, ce qui détruira tout à l’exception des volumes externes :

Terminal window
docker-compose down

Conclusion

Docker Compose est un outil incontournable pour orchestrer facilement des applications conteneurisées. En exploitant les concepts de base tels que les services, les réseaux et les volumes, il permet de gérer des environnements multi-services avec efficacité et simplicité. Les fonctionnalités offertes, comme la gestion automatique des réseaux, la persistance des données via les volumes et l’automatisation des tâches grâce aux commandes CLI, rendent Docker Compose indispensable pour déployer des applications cohérentes et reproductibles. Maîtriser Docker Compose vous aide à simplifier vos déploiements et à maintenir des configurations robustes.