Retour au cours

infra / docker-compose

Réseaux personnalisés

Leçon 71 exercice

Explication

Ce que vous allez apprendre

  • Comprendre le réseau bridge par défaut que Compose crée automatiquement pour un projet
  • Créer des réseaux personnalisés pour isoler des groupes de services entre eux
  • Utiliser la résolution DNS interne : contacter un service par son nom, jamais par son IP
  • Bloquer tout accès Internet sortant d'un réseau sensible avec internal: true
  • Connecter un service à un réseau déjà créé par un autre projet Compose (external: true)

Dans quel contexte ?

Sur la stack boutique-api, le service frontend, exposé publiquement sur Internet, n'a strictement aucune raison de pouvoir contacter directement la base de données db qui contient les informations de paiement des clients. Pourtant, avec la configuration réseau par défaut de Compose, c'est exactement ce qui se passe : tous les services d'un même projet se voient et se parlent librement. Cette leçon corrige ce problème avec des réseaux séparés.

Le comportement par défaut de Compose

D'abord, il faut savoir ce que fait Compose sans aucune configuration réseau particulière : il place tous les services d'un projet sur un même réseau, où ils se contactent par leur nom, comme un carnet d'adresses interne automatique.

Pratique, mais parfois trop permissif

C'est pratique pour commencer, mais ça pose un problème de sécurité : une base de données n'a par exemple aucune raison d'être joignable directement depuis un service "frontend" exposé au public. Tout le monde parle à tout le monde, sans distinction.

L'idée : segmenter comme des VLAN

La solution consiste à créer des réseaux personnalisés, un peu comme des VLAN séparés dans un réseau d'entreprise. Chaque groupe de machines ne voit alors que ce dont il a réellement besoin, et rien de plus.

Comment un service en trouve un autre

Une fois les réseaux définis, il reste à comprendre comment les services se trouvent entre eux. Chaque service connecté à un réseau Compose reçoit automatiquement un enregistrement DNS interne portant son nom. Le service api peut donc contacter la base simplement en visant l'hôte db, sans connaître son adresse IP, qui peut de toute façon changer à chaque redémarrage.

Un service absent d'un réseau ne le voit pas

Il faut bien retenir une règle simple : un service qui n'est PAS connecté à un réseau donné ne peut tout simplement pas contacter les services de ce réseau, même s'ils tournent sur la même machine hôte. C'est exactement l'effet d'isolation recherché.

Bonne pratique

Donne toujours un rôle clair à chaque réseau plutôt que de tout regrouper : un public_net pour ce qui doit être joignable de l'extérieur, un private_net pour ce qui ne doit parler qu'en interne. Un service critique comme une base de données ne devrait jamais figurer sur le même réseau qu'un service exposé publiquement.

Aller plus loin : internal et external

Deux options méritent d'être connues. Un réseau marqué internal: true empêche tout trafic sortant vers Internet — utile pour un réseau de base de données qui n'a besoin de parler qu'aux autres services internes. À l'inverse, external: true permet de rejoindre un réseau déjà créé ailleurs, par exemple partagé entre plusieurs projets Compose, comme un reverse proxy central.

Le piège à éviter

Le piège le plus courant reste de mettre tous les services sur un seul réseau "par défaut" sans jamais se demander qui doit vraiment parler à qui. Cela fonctionne, mais annule tout le bénéfice de sécurité de la segmentation.

Type de réseauDéclarationEffet
Bridge par défautAucune (implicite)Tous les services du projet se voient entre eux
Réseau customnetworks: au niveau service et racineIsole des groupes de services
internal: trueSur le réseau racineAucun accès sortant vers Internet
external: trueSur le réseau racineRejoint un réseau créé par un autre projet

Maintenant que la stack est isolée proprement au niveau réseau, la leçon suivante aborde un besoin différent : activer ou désactiver certains services selon le contexte, avec les profiles.

Commandes & code

Réseaux Compose

Par défaut, Compose crée un réseau bridge unique où tous les services se résolvent par leur nom. Des réseaux custom permettent d'isoler des groupes de services.

yaml
services:
  frontend:
    image: myorg/frontend:latest
    networks:
      - public_net

  api:
    build: ./api
    networks:
      - public_net      # joignable depuis "frontend"
      - private_net      # joignable depuis "db" uniquement

  db:
    image: postgres:16
    networks:
      - private_net      # PAS accessible depuis "frontend" -> isolation

networks:
  public_net:
  private_net:
    internal: true       # aucun accès sortant vers Internet depuis ce réseau
yaml
# Alias réseau et sous-réseau custom
services:
  api:
    build: ./api
    networks:
      backend:
        aliases:
          - api.internal
        ipv4_address: 172.28.0.10

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16
bash
# Lister les réseaux créés par le projet
docker network ls

# Inspecter : voir les conteneurs connectés, IP, sous-réseau
docker network inspect docker-compose_public_net

# Tester la résolution DNS interne entre services
docker compose exec api ping -c 2 db
docker compose exec api nslookup db
yaml
# Rejoindre un réseau externe déjà créé (ex: partagé entre plusieurs stacks Compose)
networks:
  shared_proxy:
    external: true
    name: traefik_proxy

Résumé

  • Chaque service voit les autres par leur NOM DE SERVICE comme hostname.
  • internal: true bloque tout accès Internet sortant depuis ce réseau.
  • aliases donne des noms DNS supplémentaires à un service sur un réseau.
  • external: true connecte à un réseau créé hors de ce fichier Compose.

Exercices pratiques

1 disponible
1

Mission : le frontend qui parle directement à la base de paiement

Objectif : Segmenter une stack en réseaux isolés et repérer un service qui reste un point de pivot.

Contexte

Sur boutique-api, aucune configuration réseau particulière n'a été ajoutée : frontend (exposé publiquement), api et db (qui contient les données de paiement) tournent tous sur le même réseau bridge par défaut. Un audit signale que frontend peut contacter db directement en visant simplement l'hôte db.

Segmente la stack et évalue ce que cette segmentation protège réellement.

Résoudre l’exercice →