Tutoriel Docker Compose : Démarrer avec un Exemple Simple
Blog, Développement, Tutoriels

Tutoriel Docker Compose : Démarrer avec un Exemple Simple

Vous en avez marre de jongler avec les commandes `docker run` pour lancer votre application ? Vous configurez un conteneur, puis un autre, vous créez le réseau, vous liez les volumes… et si une seule chose est oubliée, tout plante. C’est compliqué et source d’erreurs.

Docker Compose est l’outil qu’il vous faut pour arrêter ce bricolage. Il vous permet de décrire tous les services de votre application dans un seul fichier de configuration simple. Ensuite, une seule commande suffit pour tout démarrer. Ce tutoriel vous guide pas à pas pour créer votre première application multi-conteneurs avec Docker Compose grâce à un exemple concret et facile à suivre.

Qu’est-ce que Docker Compose et pourquoi l’utiliser ?

Pour faire simple, Docker Compose est un outil d’orchestration pour le développement en local. Il prend le relais quand vous avez besoin de faire fonctionner plusieurs conteneurs Docker ensemble. Le cas typique, c’est une application web qui a besoin d’une base de données.

Le cœur de l’outil est le fichier `docker-compose.yml`. C’est un simple fichier texte au format YAML dans lequel vous décrivez tous les morceaux de votre application : les services, les réseaux, les volumes… Pensez-y comme à un plan de construction. Une fois ce plan écrit, vous n’avez plus qu’à utiliser une seule commande pour tout construire et lancer.

Les avantages sont clairs :

  • Simplicité : Vous définissez toute votre infrastructure applicative dans un seul fichier. Fini les longs scripts ou les commandes à rallonge.
  • Reproductibilité : N’importe quel développeur peut cloner votre projet, lancer `docker compose up`, et obtenir exactement le même environnement de développement qui fonctionne.
  • Rapidité : Démarrer, arrêter ou reconstruire l’ensemble de votre application se fait avec des commandes courtes et directes.
  • Isolation : Compose crée un réseau dédié pour vos services, ce qui leur permet de communiquer facilement entre eux sans interférer avec d’autres projets sur votre machine.

Prérequis : Ce qu’il vous faut avant de commencer

Avant d’aller plus loin, assurez-vous d’avoir les outils nécessaires sur votre machine. Heureusement, c’est très simple.

  • Docker Engine et Docker Compose : Les deux sont indispensables. La solution la plus simple est d’installer Docker Desktop (pour Windows, macOS ou Linux). Il inclut tout ce dont vous avez besoin en une seule installation. C’est l’option fortement recommandée.
  • Un terminal : Vous aurez besoin d’une ligne de commande pour lancer les commandes Docker.
  • Un éditeur de texte : N’importe quel éditeur comme VS Code, Sublime Text ou même le Bloc-notes fera l’affaire pour créer les fichiers.
💡 Une précision importante sur la commande

Vous verrez peut-être des tutoriels plus anciens qui utilisent la commande `docker-compose` (avec un tiret). La nouvelle syntaxe standard est `docker compose` (sans tiret). C’est la version V2, directement intégrée à Docker. C’est celle que nous utiliserons dans ce guide.

Si vous ne l’avez pas déjà, vous pouvez installez la dernière version de Docker Desktop. C’est la méthode la plus directe.

Tutoriel : Créer votre première application avec Docker Compose (Exemple Python/Redis)

Nous allons créer une application web très simple en Python avec le framework Flask. Cette application se connectera à une base de données Redis pour compter le nombre de fois que la page a été visitée. C’est un exemple « Hello World » parfait pour comprendre les concepts de Docker Compose.

Étape 1 : Création de la structure du projet

Ouvrez votre terminal, créez un dossier pour le projet et placez-vous à l’intérieur.

mkdir mon-projet-compose
cd mon-projet-compose

Dans ce dossier, nous allons créer trois fichiers vides pour commencer :

  • app.py : Le code de notre application Flask.
  • requirements.txt : La liste des dépendances Python.
  • docker-compose.yml : Le fameux fichier de configuration de Compose.

Vous pouvez les créer avec la commande `touch` sur Linux/macOS ou simplement les créer manuellement avec votre éditeur.

Étape 2 : Le code de l’application (app.py)

Ouvrez le fichier `app.py` et collez-y le code suivant. C’est une application web basique qui se connecte à un service nommé `redis`.

from flask import Flask
from redis import Redis
import os

app = Flask(__name__)
# Le nom d'hôte 'redis' est reconnu grâce au réseau créé par Docker Compose
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello World! Cette page a été vue {} fois.'.format(count)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, debug=True)

Le point le plus important ici est `host=’redis’`. Normalement, vous devriez mettre une adresse IP. Mais comme Docker Compose va créer un réseau pour nous, le nom du service (`redis`) fonctionne directement comme nom d’hôte (host). C’est l’un des grands avantages.

Étape 3 : Les dépendances (requirements.txt)

Ouvrez le fichier `requirements.txt` et ajoutez les deux bibliothèques Python dont notre application a besoin.

flask
redis

Ce fichier sera utilisé par notre Dockerfile (que nous définirons indirectement dans le fichier compose) pour installer les bonnes versions des paquets.

Étape 4 : Le fichier `docker-compose.yml`

C’est le cœur de notre projet. Ouvrez le fichier `docker-compose.yml` et ajoutez ce contenu. Lisez bien les commentaires pour comprendre chaque ligne.

# Spécifie la version de la syntaxe Docker Compose. '3.8' est une version stable.
version: '3.8'

# La section où l'on définit tous nos conteneurs.
services:
  # Le premier service : notre application web.
  web:
    # 'build: .' indique à Compose de construire une image Docker
    # en utilisant le Dockerfile présent dans le dossier courant (.).
    build: .
    # Mappe le port 8000 du conteneur au port 8000 de notre machine locale.
    # Format : 'PORT_HOTE:PORT_CONTENEUR'
    ports:
      - "8000:8000"
    # Monte le dossier courant de notre machine dans /app du conteneur.
    # Permet de modifier le code en local et de voir les changements sans reconstruire l'image.
    volumes:
      - .:/app

  # Le deuxième service : notre base de données Redis.
  redis:
    # 'image: "redis:alpine"' indique à Compose de ne pas construire d'image,
    # mais de télécharger l'image "redis" avec le tag "alpine" depuis Docker Hub.
    image: "redis:alpine"

Ce fichier définit donc deux services web : `web` et `redis`. Le premier est construit à partir de notre code, le second est une image Docker standard.

Étape 5 : Lancement de l’application

Maintenant que tout est en place, retournez dans votre terminal (assurez-vous d’être bien dans le dossier `mon-projet-compose`) et lancez la commande magique :

docker compose up -d

L’option `-d` signifie « detached ». Elle lance les conteneurs en arrière-plan et vous rend la main sur le terminal. La première fois, Docker va télécharger l’image de Redis et construire l’image de votre application web. Cela peut prendre une minute.

Pour vérifier que tout fonctionne :

  • Ouvrez votre navigateur et allez à l’adresse `http://localhost:8000` ou `http://127.0.0.1:8000`. Vous devriez voir « Hello World! Cette page a été vue 1 fois. »
  • Actualisez la page, le compteur doit augmenter.
  • Dans votre terminal, tapez `docker compose ps` pour voir l’état de vos conteneurs.

Analyse détaillée du fichier `docker-compose.yml`

Le fichier `docker-compose.yml` que nous avons créé est simple, mais il contient les concepts les plus importants. Décortiquons-le.

  • `version` : Définit la version du format de fichier Compose. Cela garantit que le fichier est interprété correctement. ‘3.8’ est un bon choix courant.
  • `services` : C’est la clé principale du fichier. Chaque sous-élément est un conteneur qui sera lancé. Nous avons défini `web` et `redis`.
  • `build` : Cette instruction est utilisée pour le service `web`. `build: .` signifie « Construis une image Docker à partir des instructions trouvées dans le `Dockerfile` du dossier actuel ». Même si nous n’avons pas créé de `Dockerfile` nous-mêmes, cette configuration de base en génère un implicitement pour une application Python. Pour des projets plus complexes, vous créeriez un fichier `Dockerfile` explicite pour plus de contrôle. Vous trouverez plus d’informations dans la documentation officielle du Dockerfile.
  • `image` : Utilisée pour le service `redis`. Au lieu de construire une image, `image: « redis:alpine »` demande à Docker de télécharger (`pull`) une image déjà existante depuis Docker Hub. C’est ce qu’on fait pour tous les services standards (bases de données, serveurs web, etc.).
  • `ports` : Ouvre une porte entre votre machine (l’hôte) et le conteneur. ` »8000:8000″` signifie que tout ce qui arrive sur le port 8000 de votre machine est redirigé vers le port 8000 du conteneur `web`.
  • `volumes` : Lie un dossier de votre machine à un dossier dans le conteneur. `.:/app` est très utile pour le développement : le `.` représente votre dossier de projet, et `/app` est le dossier de travail (`WORKDIR`) à l’intérieur du conteneur. Grâce à ça, vous pouvez modifier votre code `app.py` en local, et les changements sont immédiatement visibles dans le conteneur sans avoir à le reconstruire.

Les commandes Docker Compose essentielles à connaître

En plus de `docker compose up`, il existe une poignée de commandes que vous utiliserez constamment pour gérer votre environnement.

💡 Astuce

Ces commandes doivent toujours être lancées depuis le dossier où se trouve votre fichier `docker-compose.yml`.

Commande Description Cas d’usage
docker compose up Crée et démarre tous les services définis dans le fichier `docker-compose.yml`. La commande principale pour lancer votre projet. Utilisez `up -d` pour le lancer en arrière-plan.
docker compose down Arrête et supprime les conteneurs, les réseaux et les volumes créés par `up`. Quand vous avez fini de travailler et que vous voulez nettoyer votre environnement.
docker compose ps Liste tous les conteneurs en cours d’exécution pour le projet en cours et affiche leur état. Pour vérifier rapidement si vos services sont bien démarrés ou s’ils ont planté.
docker compose logs Affiche les logs (sorties console) de tous les services. Indispensable pour déboguer. Utilisez `logs -f web` pour suivre les logs du service `web` en direct.
docker compose exec Exécute une commande à l’intérieur d’un conteneur en cours d’exécution. Très utile pour ouvrir un shell dans un conteneur : `exec web /bin/sh`.
docker compose build Force la reconstruction des images pour les services qui ont une instruction `build`. À utiliser quand vous modifiez le `Dockerfile` ou les dépendances (`requirements.txt`).

FAQ – Questions fréquentes sur Docker Compose

Quelle est la différence entre Docker et Docker Compose ?

C’est une question très courante. Pensez-y de cette façon :

  • Docker gère des conteneurs individuels. C’est le moteur qui construit et exécute les images. La commande `docker run` est faite pour lancer un seul conteneur.
  • Docker Compose est un outil d’orchestration qui gère plusieurs conteneurs en même temps. Il utilise Docker en coulisses mais simplifie la définition et la liaison des différents services de votre application.

Dois-je utiliser `docker-compose` ou `docker compose` ?

Utilisez `docker compose` (sans tiret). C’est la version la plus récente, intégrée directement dans l’interface de ligne de commande de Docker. La version avec le tiret (`docker-compose`) est l’ancienne version V1, qui était un script Python séparé. La nouvelle version est la norme aujourd’hui.

Comment passer des variables d’environnement à un service ?

C’est très simple. Vous pouvez utiliser la clé `environment` dans la définition de votre service dans le fichier `docker-compose.yml`. Cela permet de configurer votre application sans coder les valeurs en dur.

services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - FLASK_ENV=development
      - DATABASE_URL=postgresql://user:password@db:5432/mydatabase

Ces variables d’environnement seront alors accessibles depuis votre code, par exemple avec `os.environ.get(‘FLASK_ENV’)` en Python.

Vous pourriez également aimer...