Retour au cours

infra / docker-compose

Profiles : dev, prod et services optionnels

Leçon 81 exercice

Explication

Ce que vous allez apprendre

  • Comprendre le profil implicite "default" appliqué aux services sans profiles:
  • Activer un ou plusieurs profils avec --profile ou la variable COMPOSE_PROFILES
  • Isoler les outils de développement (adminer, mailhog) des services essentiels
  • Placer un job d'outillage ponctuel dans un profil pour qu'il ne tourne jamais par accident
  • Éviter la duplication de fichiers Compose entre environnements grâce à un seul fichier

Dans quel contexte ?

L'équipe du projet boutique-api veut qu'un simple docker compose up en local démarre aussi Adminer (interface d'administration PostgreSQL) et MailHog (serveur mail factice), sans jamais les voir apparaître par erreur en production. Plutôt que de maintenir deux fichiers Compose distincts qui finiraient par diverger, cette leçon montre comment un seul fichier peut représenter les deux configurations grâce aux profils.

Un besoin qui varie selon le contexte

D'abord, un constat simple : sur un projet réel, on n'a pas toujours besoin des mêmes services. En développement, on veut souvent un outil d'administration de base de données ou un faux serveur mail ; en production, sûrement pas.

Une mauvaise solution : dupliquer le fichier

Une première idée viendrait à l'esprit : dupliquer le fichier Compose pour chaque cas. Mais c'est une mauvaise solution, car les deux fichiers finissent toujours par diverger avec le temps, et cela devient source d'erreurs.

La solution : des interrupteurs de scène

Les profiles résolvent ce problème autrement. Imagine des interrupteurs de scène dans une salle de spectacle : certaines lumières sont toujours allumées, d'autres ne s'allument que si tu actives la scène correspondante.

Ce qui est "toujours allumé" par défaut

Un service SANS profiles: fait partie du profil implicite "default" et démarre toujours avec un simple docker compose up. C'est le cas normal pour tes services essentiels, comme l'API ou la base de données.

Ce qui reste éteint tant qu'on ne l'active pas

À l'inverse, un service avec profiles: [dev] reste invisible tant que ce profil n'est pas activé explicitement, que ce soit via l'option --profile en ligne de commande ou la variable COMPOSE_PROFILES. Un même fichier Compose peut ainsi représenter plusieurs configurations, sans jamais se dupliquer.

Configuration du serviceDémarre avec docker compose up seul ?Démarre avec --profile dev ?
Pas de profiles: (default)OuiOui
profiles: [dev]NonOui
profiles: [tooling]NonNon (il faut --profile tooling)

Attention à une idée fausse fréquente

Un piège classique consiste à croire qu'un service "profile-only" démarre automatiquement dès que ses dépendants tournent. Ce n'est pas le cas : il faut toujours l'activer explicitement, sinon il reste totalement invisible pour Compose.

Piège fréquent

Un service avec profiles: [tooling] placé en dépendance (depends_on) d'un service "default" ne démarre PAS automatiquement avec lui : Compose refuse simplement de créer la dépendance si le profil n'est pas activé. Vérifie toujours qu'un service et tout ce dont il dépend partagent des profils compatibles.

Un cas d'usage particulier : l'outillage

Pour aller plus loin, pense aux services de type "outillage", comme des tests de charge ou des scripts ponctuels. Ils devraient presque toujours être placés dans un profil séparé, pour ne jamais tourner par accident avec un simple up.

Un dernier conseil d'organisation

Enfin, résiste à la tentation de multiplier les profils sans convention claire : cela rend vite la stack difficile à comprendre pour un nouvel arrivant dans l'équipe. Mieux vaut peu de profils, mais bien nommés et documentés.

La leçon suivante aborde un problème voisin, mais résolu différemment : fusionner plusieurs fichiers YAML entre eux, plutôt que d'activer des sous-ensembles d'un même fichier.

Commandes & code

Profiles

Les profiles permettent d'activer/désactiver des services selon le contexte (dev, debug, tooling) sans dupliquer le fichier.

yaml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    # Pas de "profiles" -> toujours actif ("default")

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: changeme
    # Toujours actif aussi

  adminer:
    image: adminer:latest
    ports:
      - "8081:8080"
    profiles:
      - dev              # visible seulement si le profile "dev" est activé

  mailhog:
    image: mailhog/mailhog
    ports:
      - "8025:8025"
    profiles:
      - dev
      - debug

  load_test:
    image: grafana/k6
    profiles:
      - tooling           # ne tourne jamais avec un simple "up"
    command: ["run", "/scripts/load-test.js"]
bash
# Sans profile : seuls "api" et "db" démarrent
docker compose up -d

# Active le profile "dev" en plus des services par défaut
docker compose --profile dev up -d

# Active plusieurs profiles
docker compose --profile dev --profile debug up -d

# Variante : via variable d'environnement
COMPOSE_PROFILES=dev,debug docker compose up -d

# Lancer explicitement un service "profile-only" une seule fois
docker compose --profile tooling run --rm load_test

Résumé

  • Un service sans profiles: démarre toujours (profile implicite "default").
  • --profile <nom> ou COMPOSE_PROFILES active des groupes de services.
  • Idéal pour séparer outils de dev (adminer, mailhog) des services essentiels.

Exercices pratiques

1 disponible
1

Mission : mailhog s'invite en production

Objectif : Corriger un oubli de profile et isoler correctement un job d'outillage.

Contexte

Une stagiaire sur boutique-api ajoute profiles: [dev] au service adminer, mais oublie de faire de même pour mailhog, qu'elle laisse sans profiles:. L'équipe veut aussi ajouter un service load_test (image grafana/k6) qui ne doit absolument jamais démarrer par accident.

Corrige la configuration des profiles avant le prochain déploiement en production.

Résoudre l’exercice →