feat: docs
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
---
|
||||
title: Docker Compose
|
||||
description: Décrire et lancer une application composée de plusieurs services.
|
||||
---
|
||||
|
||||
## Le problème résolu par Compose
|
||||
|
||||
`docker run` lance un conteneur. Une application réelle utilise souvent plusieurs services : frontend, backend, base de données, stockage, serveur de mail et reverse proxy.
|
||||
|
||||
Lancer chaque conteneur à la main, dans le bon ordre et avec les bons réseaux, ports et variables, devient vite ingérable.
|
||||
|
||||
Docker Compose décrit toute la stack dans un fichier YAML déclaratif et la pilote avec une seule commande :
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.dev.yml up
|
||||
docker compose -f docker-compose.dev.yml down
|
||||
```
|
||||
|
||||
## Anatomie d'un fichier Compose
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile.dev
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
POSTGRES_HOST: postgres
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
## Les notions principales
|
||||
|
||||
### services
|
||||
|
||||
Chaque clé représente un service. Il utilise soit `image:` pour récupérer une image existante, soit `build:` pour construire une image depuis un Dockerfile.
|
||||
|
||||
### depends_on et healthcheck
|
||||
|
||||
`depends_on` organise le démarrage. Avec `condition: service_healthy`, le backend n'attend pas seulement que le conteneur PostgreSQL existe : il attend que la base soit prête à accepter des connexions.
|
||||
|
||||
### environment
|
||||
|
||||
Les variables configurent le conteneur. La syntaxe `${VAR}` lit généralement la valeur depuis un fichier `.env`.
|
||||
|
||||
### networks et volumes
|
||||
|
||||
Les réseaux et volumes sont déclarés une fois, puis associés aux services qui en ont besoin.
|
||||
|
||||
## Superposer plusieurs fichiers
|
||||
|
||||
Un projet peut séparer les usages :
|
||||
|
||||
| Fichier | Usage |
|
||||
| --- | --- |
|
||||
| `docker-compose.dev.yml` | Développement avec hot-reload et bind mounts |
|
||||
| `docker-compose.prod.yml` | Production avec images préconstruites et politique de redémarrage |
|
||||
| `docker-compose.local-e2e.yml` | Surcharge pour les tests e2e |
|
||||
|
||||
Le second fichier surcharge le premier :
|
||||
|
||||
```bash
|
||||
docker compose \
|
||||
-f docker-compose.prod.yml \
|
||||
-f docker-compose.local-e2e.yml \
|
||||
up
|
||||
```
|
||||
|
||||
<Callout title="Compose orchestre, il ne remplace pas les images" type="info">
|
||||
Le Dockerfile décrit comment construire une image. Le fichier Compose décrit comment lancer, configurer et relier plusieurs instances d'images.
|
||||
</Callout>
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Mapping de ports
|
||||
description: Publier un port du conteneur vers l'hôte sans exposer toute la stack.
|
||||
---
|
||||
|
||||
## Réseau interne et monde extérieur
|
||||
|
||||
Le réseau bridge est privé. Les services communiquent entre eux, mais le navigateur ou le terminal de l'hôte ne peut pas les joindre tant qu'aucun port n'est publié.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
nginx:
|
||||
ports:
|
||||
- "8080:80"
|
||||
- "8443:443"
|
||||
```
|
||||
|
||||
La syntaxe est :
|
||||
|
||||
```text
|
||||
PORT_HÔTE:PORT_CONTENEUR
|
||||
```
|
||||
|
||||
`8443:443` redirige le port 8443 de la machine vers le port 443 écouté par Nginx dans le conteneur.
|
||||
|
||||
## Exposer uniquement le point d'entrée
|
||||
|
||||
Dans une stack classique, PostgreSQL, le backend et le frontend n'ont pas forcément de section `ports:`. Ils restent accessibles depuis le réseau Docker, mais pas depuis l'extérieur.
|
||||
|
||||
Seul Nginx publie un port. Il devient le point d'entrée et route ensuite les requêtes vers les services internes.
|
||||
|
||||
```text
|
||||
navigateur
|
||||
│
|
||||
▼
|
||||
port publié de Nginx
|
||||
│
|
||||
├──► frontend
|
||||
└──► backend ──► postgres
|
||||
```
|
||||
|
||||
## Éviter les collisions
|
||||
|
||||
Le port interne d'un service reste le même, tandis que le port hôte peut changer :
|
||||
|
||||
```yaml
|
||||
# Stack A
|
||||
ports:
|
||||
- "8443:443"
|
||||
|
||||
# Stack B
|
||||
ports:
|
||||
- "8444:443"
|
||||
```
|
||||
|
||||
Ce principe permet à plusieurs workers de test de lancer la même stack sur des plages de ports différentes.
|
||||
|
||||
## Restreindre une publication à la machine
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
ports:
|
||||
- "127.0.0.1:15432:5432"
|
||||
```
|
||||
|
||||
Le préfixe `127.0.0.1` rend le port accessible depuis le serveur pour la maintenance, sans l'ouvrir sur l'adresse publique.
|
||||
|
||||
<Callout title="Principe de sécurité" type="warning">
|
||||
Ne publie pas une base de données sur toutes les interfaces sans nécessité. Sans le préfixe 127.0.0.1, un mapping comme 5432:5432 peut exposer PostgreSQL sur Internet si le pare-feu le permet.
|
||||
</Callout>
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "Orchestration",
|
||||
"description": "Faire fonctionner plusieurs services ensemble",
|
||||
"pages": ["docker-compose", "volumes", "reseaux", "mapping-de-ports"]
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Réseaux Docker
|
||||
description: Relier les services avec un réseau privé et la résolution DNS interne.
|
||||
---
|
||||
|
||||
## Des conteneurs isolés
|
||||
|
||||
Chaque conteneur possède sa propre pile réseau. Pour que le backend puisse joindre PostgreSQL et que Nginx puisse joindre le frontend, leurs conteneurs doivent partager un réseau.
|
||||
|
||||
## Réseau bridge et noms de services
|
||||
|
||||
Compose crée un réseau et y attache les services. Sur ce réseau, Docker fournit un DNS interne : chaque service est joignable avec son nom.
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
|
||||
services:
|
||||
postgres:
|
||||
networks:
|
||||
- app-network
|
||||
|
||||
backend:
|
||||
networks:
|
||||
- app-network
|
||||
environment:
|
||||
POSTGRES_HOST: postgres
|
||||
MINIO_HOST: minio
|
||||
SMTP_HOST: mailpit
|
||||
```
|
||||
|
||||
Le backend se connecte à la base avec l'hôte `postgres`. Docker résout ce nom vers l'adresse interne du conteneur correspondant.
|
||||
|
||||
Les adresses IP peuvent changer à chaque redémarrage ; les noms de services restent stables.
|
||||
|
||||
<Callout title="localhost reste local" type="warning">
|
||||
À l'intérieur d'un conteneur, localhost désigne ce même conteneur. Pour joindre un autre service, utilise son nom Compose, jamais localhost.
|
||||
</Callout>
|
||||
|
||||
## Isolation entre les stacks
|
||||
|
||||
Deux projets Compose distincts créent chacun leur réseau bridge. Leurs services ne se voient pas par défaut.
|
||||
|
||||
Cette isolation permet notamment de lancer plusieurs stacks de tests en parallèle sans qu'elles communiquent entre elles.
|
||||
|
||||
## Segmenter l'application
|
||||
|
||||
Un service peut appartenir à plusieurs réseaux. On peut ainsi exposer Nginx au réseau frontal tout en gardant PostgreSQL uniquement sur un réseau interne :
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
public:
|
||||
private:
|
||||
|
||||
services:
|
||||
nginx:
|
||||
networks:
|
||||
- public
|
||||
- private
|
||||
|
||||
backend:
|
||||
networks:
|
||||
- private
|
||||
|
||||
postgres:
|
||||
networks:
|
||||
- private
|
||||
```
|
||||
|
||||
Seuls les services partageant un réseau peuvent communiquer directement.
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Volumes
|
||||
description: Conserver les données indépendamment du cycle de vie des conteneurs.
|
||||
---
|
||||
|
||||
## Un conteneur est éphémère
|
||||
|
||||
Le système de fichiers propre à un conteneur est jetable. Les écritures disparaissent lorsque le conteneur est détruit ou recréé. Pour une base de données, ce comportement serait inacceptable.
|
||||
|
||||
Un volume est un stockage persistant géré par Docker et découplé du conteneur : le conteneur va et vient, le volume reste.
|
||||
|
||||
## Volume nommé
|
||||
|
||||
```yaml
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
```
|
||||
|
||||
Cette configuration monte le volume `postgres_data` sur `/var/lib/postgresql/data`, l'emplacement où PostgreSQL écrit ses données.
|
||||
|
||||
Les données survivent à un `down` puis un `up`, tant que le volume n'est pas supprimé.
|
||||
|
||||
<Callout title="Attention à down -v" type="warning">
|
||||
docker compose down -v supprime aussi les volumes de la stack. Sur une base contenant des données importantes, cette action est destructive.
|
||||
</Callout>
|
||||
|
||||
## Où vit un volume ?
|
||||
|
||||
Le volume est stocké dans le système de fichiers du Docker Engine :
|
||||
|
||||
- directement sur l'hôte avec Linux ;
|
||||
- dans la VM Linux Docker Desktop avec Mac ou Windows.
|
||||
|
||||
Ce n'est pas un dossier du dépôt. Docker en gère l'emplacement et le cycle de vie.
|
||||
|
||||
## Bind mount : monter un dossier de l'hôte
|
||||
|
||||
En développement, on veut voir les modifications de code immédiatement dans le conteneur :
|
||||
|
||||
```yaml
|
||||
services:
|
||||
backend:
|
||||
volumes:
|
||||
- ./backend:/app
|
||||
- /app/node_modules
|
||||
- /app/dist
|
||||
```
|
||||
|
||||
### Le code local
|
||||
|
||||
`./backend:/app` monte le dossier du projet dans le conteneur. Quand un fichier est modifié sur l'hôte, le serveur dans le conteneur le voit et peut redémarrer en hot-reload.
|
||||
|
||||
### Les dépendances du conteneur
|
||||
|
||||
Le bind mount masquerait le dossier `node_modules` installé dans l'image. Le volume anonyme `/app/node_modules` le protège des fichiers absents ou incompatibles de l'hôte.
|
||||
|
||||
## Développement ou production
|
||||
|
||||
| Contexte | Stockage recommandé |
|
||||
| --- | --- |
|
||||
| Code en développement | Bind mount pour le hot-reload |
|
||||
| Dépendances internes | Volume anonyme si le bind mount les masque |
|
||||
| Données PostgreSQL | Volume nommé |
|
||||
| Code en production | Dans l'image, sans bind mount |
|
||||
| Données persistantes en production | Volume nommé et sauvegardé |
|
||||
Reference in New Issue
Block a user