# Docker Compose

### Introduction

**Docker Compose** est une commande docker permettant de définir et de gérer des applications multi-conteneurs.

La commande utilise un fichier YAML (`docker-compose.yml)` pour décrire les services, les réseaux, les volumes, et les dépendances entre les conteneurs.

Ci-dessous l'exemple d'un fichier `docker-compose.yml`. Il s'agit d'un projet web avec une API Node.js, une base de données PostgreSQL, et un reverse proxy Nginx.

```yaml
services:
  nginx:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - web

  web:
    build: ./web
    environment:
      - NODE_ENV=production
    depends_on:
      - db

  db:
    image: postgres
    environment:
      - POSTGRES_PASSWORD=secret
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

```

La "traduction" en ligne de commandes `docker` ressemblerait à ceci :

```bash
# création du volume pour PostgreSQL
docker volume create pgdata

# création de l'image pour le serveur web
docker build -t web-image ./web

# lancement des conteneurs
docker run -d --name db -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data postgres
docker run -d --name web -e NODE_ENV=production web-image
docker run -d --name nginx --network frontnet -p 80:80 -v ./nginx.conf:/etc/nginx/nginx.conf nginx

```

### Orchestration

L'orchestration d'une stack docker compose s'effectue avec la commande `docker compose`.

```bash
docker compose up # démarre les conteneurs
docker compose down # arrête et supprime les conteneurs, réseaux et volumes
docker compose build # construit les images des conteneurs
docker compose logs # affiche les logs des conteneurs
```

### Syntaxe

#### Services

La clé `services` définit les conteneurs à lancer. Chaque service représente un conteneur Docker.

```yaml
services:
  web:
    image: nginx:latest
```

Pour chaque service, les instructions suivantes sont disponibles.

<table border="1" id="bkmrk-cl%C3%A9-description-exem" style="width: 100%; border-collapse: collapse; height: 586.578px;"><thead><tr style="height: 34.1094px;"><th style="width: 18.9511%; height: 34.1094px;">**Instruction**</th><th style="width: 44.4627%; height: 34.1094px;">**Description**</th><th style="width: 36.5862%; height: 34.1094px;">**Exemple**</th></tr></thead><tbody><tr style="height: 34.1094px;"><td style="width: 18.9511%; height: 34.1094px;">`image`</td><td style="width: 44.4627%; height: 34.1094px;">Image de départ</td><td style="width: 36.5862%; height: 34.1094px;">`image: ubuntu:24:04`</td></tr><tr style="height: 34.2188px;"><td style="width: 18.9511%; height: 34.2188px;">`container_name`</td><td style="width: 44.4627%; height: 34.2188px;">Nom du conteneur</td><td style="width: 36.5862%; height: 34.2188px;">`container_name: mon_web`</td></tr><tr style="height: 85.375px;"><td style="width: 18.9511%; height: 85.375px;">`ports`</td><td style="width: 44.4627%; height: 85.375px;">Mappe les ports de la machine hôte vers le conteneur</td><td style="width: 36.5862%; height: 85.375px;">```yaml
ports:
  - 8080:80
```

</td></tr><tr style="height: 85.375px;"><td style="width: 18.9511%; height: 85.375px;">`volumes`</td><td style="width: 44.4627%; height: 85.375px;">Monte des volumes dans le conteneur. Volume mappés ou managés.</td><td style="width: 36.5862%; height: 85.375px;">```yaml
volumes:
  - ./mon_dossier:/app
```

</td></tr><tr style="height: 85.375px;"><td style="width: 18.9511%; height: 85.375px;">`environment`</td><td style="width: 44.4627%; height: 85.375px;">Variables d'environnement</td><td style="width: 36.5862%; height: 85.375px;">```yaml
environment:
  - DEBUG=1
```

</td></tr><tr style="height: 55.2188px;"><td style="width: 18.9511%; height: 55.2188px;">`command`</td><td style="width: 44.4627%; height: 55.2188px;">Commande au démarrage du conteneur</td><td style="width: 36.5862%; height: 55.2188px;">`command: ["python", "app.py"]`</td></tr><tr style="height: 34.1094px;"><td style="width: 18.9511%; height: 34.1094px;">`depends_on`</td><td style="width: 44.4627%; height: 34.1094px;">Ordre de création des conteneurs</td><td style="width: 36.5862%; height: 34.1094px;">`depends_on: ["db"]`</td></tr><tr style="height: 76.3125px;"><td style="width: 18.9511%; height: 76.3125px;">`restart`</td><td style="width: 44.4627%; height: 76.3125px;">Politique de redémarrage (`no`, `always`, `on-failure`, `unless-stopped`)</td><td style="width: 36.5862%; height: 76.3125px;">`restart: always`</td></tr><tr style="height: 62.375px;"><td style="width: 18.9511%; height: 62.375px;">`networks`</td><td style="width: 44.4627%; height: 62.375px;">Réseaux du conteneur</td><td style="width: 36.5862%; height: 62.375px;">```yaml
networks:
  - frontend
```

</td></tr></tbody></table>

#### Volumes

La clé `volumes` permet d'automatiser la création et le montage des volumes managés.

```yaml
volumes:
  db_data # volume sans paramètres spécifiques
  external_volume:
    external: true
    name: mon_volume_externe
```

<table border="1" id="bkmrk-instruction-descript" style="width: 100%; border-collapse: collapse; height: 123.438px;"><thead><tr style="height: 34.1094px;"><th style="width: 18.9511%; height: 34.1094px;">**Instruction**</th><th style="width: 44.4627%; height: 34.1094px;">**Description**</th><th style="width: 36.5862%; height: 34.1094px;">**Exemple**</th></tr></thead><tbody><tr style="height: 55.2188px;"><td style="width: 18.9511%; height: 55.2188px;">`external`</td><td style="width: 44.4627%; height: 55.2188px;">Indique si le volume a été créé en dehors de la stack docker compose.</td><td style="width: 36.5862%; height: 55.2188px;">`external: true`</td></tr><tr style="height: 34.1094px;"><td style="width: 18.9511%; height: 34.1094px;">`name`</td><td style="width: 44.4627%; height: 34.1094px;">Nom du volume, utile avec `external`</td><td style="width: 36.5862%; height: 34.1094px;">`name: mon_volume_externe`

</td></tr></tbody></table>

#### Networks

La clé `networks` définit les différents réseaux docker de la stack.

```yaml
networks:
  reseau1:
    driver: bridge
  reseau2:
    driver: bridge
    ipam:
      config:
        - subnet: "172.16.0.0/16"
  reseau_externe:
    external: true
    name: mon_reseau_externe
```

<table border="1" id="bkmrk-instruction-descript-1" style="width: 100%; border-collapse: collapse; height: 123.438px;"><thead><tr style="height: 34.1094px;"><th style="width: 18.9511%; height: 34.1094px;">**Instruction**</th><th style="width: 44.4577%; height: 34.1094px;">**Description**</th><th style="width: 36.5912%; height: 34.1094px;">**Exemple**</th></tr></thead><tbody><tr style="height: 34.1094px;"><td style="width: 18.9511%; height: 34.1094px;">`driver`</td><td style="width: 44.4577%; height: 34.1094px;">Type de réseau (`bridge`, `host`, etc.)</td><td style="width: 36.5912%; height: 34.1094px;">`driver: bridge`</td></tr><tr style="height: 55.2188px;"><td style="width: 18.9511%; height: 55.2188px;">`external`</td><td style="width: 44.4577%; height: 55.2188px;">Indique si le réseau a été créé en dehors de la stack docker compose.</td><td style="width: 36.5912%; height: 55.2188px;">`external: true`</td></tr><tr><td style="width: 18.9511%; height: 34.1094px;">`name`</td><td style="width: 44.4577%; height: 34.1094px;">Nom du réseau, utile avec `external`</td><td style="width: 36.5912%; height: 34.1094px;">`name: mon_reseau_externe`

</td></tr><tr><td style="width: 18.9511%;">`ipam`</td><td style="width: 44.4577%;">Configuration IP du réseau</td><td style="width: 36.5912%;">Voir exemple ci-dessus.

</td></tr></tbody></table>