Aller au contenu principal

Introduction à Docker Compose

logo docker-compose

Lorsqu’on utilise juste Docker, pouvoir gérer plusieurs conteneurs différents peut vite devenir fastidieux. Docker Compose est une première solution pour les orchestrer plus facilement.

Introduction

Docker Compose intervient en tant qu'outil essentiel. Docker Compose est une extension de Docker qui permet de définir et de gérer des applications multi-conteneurs grâce à des fichiers de configuration simples utilisant le langage YAML. Plutôt que de gérer manuellement chaque conteneur individuellement, Docker Compose permet de déclarer les services, les réseaux, les volumes dans un seul fichier, ce qui simplifie considérablement le processus de déploiement.

Dans ce tutoriel, nous verrons les principales fonctionnalités, mais attardons pour commencer sur son installation et ensuite sur son fichier de configuration écrit en yaml.

Installation de docker-compose

attention

Attention désormais Docker Compose est un plugin de la CLI Docker-CE !

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

sudo apt-get update
sudo apt-get 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-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

On vérifie :

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, 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 YAML :

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 :

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 :

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 :

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 :

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 :

docker-compose stop

Start

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

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 :

docker-compose down

Plus d'infos

Vidéos