Save France
Developpement

Conteneurisation

Architecture Docker et Docker Compose pour le développement et la production

Introduction

Le projet utilise Docker et Docker Compose pour la conteneurisation de tous les services. Cette approche garantit une cohérence entre les environnements de développement, de review et de production, et simplifie le déploiement.

Vue d'ensemble

L'architecture conteneurisée comprend plusieurs services :

  • Caddy : Reverse proxy et serveur web avec gestion automatique du SSL
  • Front : Application Nuxt.js (frontend)
  • API : Application Symfony avec FrankenPHP
  • DB : Base de données PostgreSQL
  • Adminer : Interface web pour la gestion de la base de données
  • Mails : Serveur SMTP de test (Mailpit)
  • Gotenberg : Service de génération de PDF
flowchart TD
    A[Utilisateur] --> B[Caddy:80/443]
    B --> C[Front:3000]
    B --> D[API]
    B --> E[Adminer:8080]
    B --> F[Mails:8025]
    D --> G[DB:5432]
    D --> H[Gotenberg:3000]
    C --> D
    style B fill:#4CAF50
    style C fill:#42B883
    style D fill:#000000
    style G fill:#336791

Architecture des services

Caddy

Reverse proxy principal qui gère le routage et le SSL automatique.

Configuration :

  • Ports : 80, 443, 24678 (WebSocket pour HMR)
  • Image : caddy:2-alpine
  • Volumes : ./Caddyfile, caddy_data, caddy_config
  • Variables d'environnement : HOST

Routage :

  • {$HOST} → Frontend (port 3000)
  • api.{$HOST} → API Symfony
  • mails.{$HOST} → Mailpit
  • adminer.{$HOST} → Adminer

Frontend (Nuxt)

Application Nuxt.js avec deux modes : développement et production.

Développement (Dockerfile.dev) :

FROM node:22-alpine
WORKDIR /app
COPY ./sources .
RUN npm install
EXPOSE 3000
CMD ["npm", "run", "dev"]

Production (Dockerfile) :

  • Build multi-stage avec optimisation
  • Utilisateur non-root (nuxtjs:nodejs)
  • Port 80
  • Application pré-compilée

Variables d'environnement :

  • NUXT_HOST : Adresse d'écoute (0.0.0.0)
  • NUXT_BASE_API : URL de l'API backend
  • NUXT_PUBLIC_MATOMO_HOST : Host Matomo
  • NUXT_PUBLIC_MATOMO_SITE_ID : ID du site Matomo
  • FRONT_PASS : Mot de passe pour l'accès frontend

API (Symfony)

Application Symfony avec FrankenPHP pour de meilleures performances.

Base (Dockerfile - target: base) :

FROM dunglas/frankenphp:1.4.4-php8.4.4 AS base
# Installation des extensions PHP
# Configuration Blackfire
# Configuration xDebug

Production (Dockerfile - target: prod) :

  • Installation des dépendances Composer optimisées
  • Autoloader optimisé
  • Permissions configurées

Extensions PHP :

  • pdo, pdo_pgsql, pgsql : Support PostgreSQL
  • apcu, opcache : Cache et optimisation
  • intl, zip : Fonctionnalités supplémentaires
  • xdebug : Débogage (développement)
  • blackfire : Profiling

Variables d'environnement :

  • APP_ENV : Environnement (dev/prod)
  • APP_SECRET : Secret Symfony
  • WWW_DATA_UID : UID pour www-data (synchronisation avec l'hôte)
  • SYMFONY_TRUSTED_PROXIES : Configuration proxy
  • SERVER_NAME : Nom du serveur
  • CADDY_GLOBAL_OPTIONS : Options Caddy

Base de données (PostgreSQL)

Base de données PostgreSQL 17.2 Alpine.

Configuration :

  • Port : 5432
  • Image : postgres:17.2-alpine
  • Volume : database (persistance des données)
  • Healthcheck : Vérification de disponibilité

Variables d'environnement :

  • POSTGRES_USER : app
  • POSTGRES_PASSWORD : app
  • POSTGRES_DB : app
  • PGDATA : /var/lib/postgresql/data/pgdata

Services auxiliaires

Adminer :

  • Interface web pour la gestion de la base de données
  • Port : 8080
  • Design : nette

Mailpit :

  • Serveur SMTP de test pour le développement
  • Port : 8025
  • Interface web pour visualiser les emails

Gotenberg :

  • Service de génération de PDF
  • Port : 3000
  • Utilisé pour la génération de contrats

Environnements

Développement (compose.yml)

Configuration complète avec tous les services et outils de développement.

Caractéristiques :

  • Volumes montés pour le hot-reload
  • xDebug activable
  • Mailpit pour les emails
  • Adminer pour la base de données
  • HMR (Hot Module Replacement) via WebSocket

Démarrage :

make up
# ou
docker compose up -d

Certificat SSL local :

make ssl
# Copie le certificat root CA depuis Caddy

Production (compose.prod.yml)

Configuration optimisée pour la production.

Caractéristiques :

  • Images pré-buildées depuis le registry
  • Pas de volumes de développement
  • Healthchecks configurés
  • Variables d'environnement de production

Services :

  • Frontend : Image depuis registry
  • API : Image depuis registry
  • DB : PostgreSQL avec persistance
  • Gotenberg : Service de génération PDF

Review (compose.review.yml)

Configuration pour les environnements de review (branches GitLab).

Caractéristiques :

  • Images depuis le registry GitLab
  • Labels Roadie pour le routage
  • Configuration similaire à la production
  • Variables d'environnement spécifiques

Labels Roadie :

  • roadie.front.host=FRONT
  • roadie.api.host=API
  • roadie.mails.host=MAILS
  • roadie.adminer.host=ADMINER

Configuration Caddy

Le fichier Caddyfile configure le reverse proxy :

{$HOST} {
    tls internal
    reverse_proxy front:3000
}

{$HOST}:24678 {
    tls internal
    @websockets {
        header Connection Upgrade
        header Upgrade websocket
    }
    reverse_proxy @websockets front:24678
}

api.{$HOST} {
    tls internal
    reverse_proxy api
}

mails.{$HOST} {
    tls internal
    reverse_proxy mails:8025
}

adminer.{$HOST} {
    tls internal
    reverse_proxy adminer:8080
}

Fonctionnalités :

  • SSL automatique avec certificats internes
  • Support WebSocket pour HMR
  • Routage par sous-domaine
  • Configuration TLS interne

Volumes

Volumes nommés :

  • caddy_data : Données Caddy (certificats, cache)
  • caddy_config : Configuration Caddy
  • database : Données PostgreSQL

Volumes montés (développement) :

  • ./front/sources:/app : Code source frontend
  • ./api/sources:/app : Code source API
  • ./Caddyfile:/etc/caddy/Caddyfile : Configuration Caddy

Commandes Makefile

Démarrage et arrêt

make setup    # Configuration initiale (copie .env, configure UID/GID)
make up       # Démarre les conteneurs
make down     # Arrête les conteneurs
make ssl      # Copie le certificat SSL depuis Caddy

Accès aux conteneurs

make api      # Shell dans le conteneur API (utilisateur www-data)
make front    # Shell dans le conteneur frontend (utilisateur node)

Logs

make api-logs    # Logs du conteneur API
make front-logs  # Logs du conteneur frontend

Linting et tests

make api:lint     # Lint du code PHP (phpcs, rector, phpstan)
make front:lint   # Lint du code frontend (npm run check)
make tests        # Exécute les tests PHPUnit

Maintenance

make reset        # Rebuild complet des conteneurs (destructif)
make fixtures     # Charge les fixtures dans la base de données
make prepare-test # Prépare l'environnement de test

xDebug

make xdebug-enable # Active xDebug dans le conteneur API

Variables d'environnement

Fichier .env

Le fichier .env (copié depuis .env.example lors de make setup) contient :

Configuration générale :

  • HOST : Domaine principal (ex: save-france.local)
  • HTTP_PORT : Port HTTP (défaut: 80)
  • HTTPS_PORT : Port HTTPS (défaut: 443)
  • MAILHOG_PORT : Port Mailpit (défaut: 8025)

Frontend :

  • FRONT_PASS : Mot de passe pour l'accès frontend
  • NUXT_NITRO_PRESET : Preset Nitro (défaut: node-server)
  • NUXT_PUBLIC_MATOMO_HOST : Host Matomo
  • NUXT_PUBLIC_MATOMO_SITE_ID : ID du site Matomo

API :

  • APP_ENV : Environnement Symfony (dev/prod/test)
  • WWW_DATA_UID : UID pour www-data (synchronisé automatiquement)
  • XDEBUG_CLIENT_HOST : Host pour xDebug (détecté automatiquement)
  • BLACKFIRE_CLIENT_ID : ID client Blackfire (optionnel)
  • BLACKFIRE_CLIENT_TOKEN : Token Blackfire (optionnel)

Stripe :

  • NUXT_PUBLIC_STRIPE_PUBLISHABLE_KEY : Clé publique Stripe
  • NUXT_STRIPE_SECRET_KEY : Clé secrète Stripe
  • STRIPE_API_KEY : Clé API Stripe (backend)

Autres services :

  • GOTENBERG_DSN : DSN Gotenberg
  • YOUSIGN_API_KEY : Clé API Yousign
  • BREVO_API_KEY : Clé API Brevo

Healthchecks

Les services critiques ont des healthchecks configurés :

API :

healthcheck:
  test: curl -f http://localhost:2019/metrics || exit 1
  start_period: 3s
  interval: 30s
  retries: 10

Frontend (production) :

healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Base de données :

healthcheck:
  test: [ "CMD-SHELL", "pg_isready -U app -d app" ]
  interval: 10s
  retries: 5
  start_period: 30s
  timeout: 10s

Bonnes pratiques

Développement

  1. Utiliser make setup lors de la première installation
  2. Vérifier les UID/GID pour éviter les problèmes de permissions
  3. Utiliser les volumes montés pour le hot-reload
  4. Activer xDebug uniquement quand nécessaire (make xdebug-enable)
  5. Vérifier les logs en cas de problème (make api-logs, make front-logs)

Production

  1. Utiliser des images optimisées depuis le registry
  2. Configurer les healthchecks pour tous les services critiques
  3. Utiliser des secrets pour les variables sensibles
  4. Limiter les ressources avec des limites CPU/mémoire
  5. Activer les logs structurés (JSON) pour le monitoring

Sécurité

  1. Ne jamais commiter le fichier .env
  2. Utiliser des utilisateurs non-root dans les conteneurs
  3. Limiter les ports exposés au strict nécessaire
  4. Utiliser des réseaux Docker pour isoler les services
  5. Mettre à jour régulièrement les images de base

Dépannage

Problèmes de permissions

Si vous avez des problèmes de permissions avec les fichiers générés :

# Vérifier l'UID dans .env
grep WWW_DATA_UID .env

# Ajuster si nécessaire
sed -i "s/WWW_DATA_UID=.*/WWW_DATA_UID=$(id -u)/g" .env

Problèmes de certificat SSL

# Régénérer le certificat
make ssl

# Vérifier dans le navigateur
# macOS : Ajouter rootCA.crt dans Keychain Access
# Linux : Ajouter dans les certificats système

Conteneur qui ne démarre pas

# Vérifier les logs
docker compose logs [service]

# Vérifier les healthchecks
docker compose ps

# Rebuild si nécessaire
docker compose build --no-cache [service]

Problèmes de réseau

# Vérifier les réseaux Docker
docker network ls

# Inspecter un réseau
docker network inspect [network_name]

# Nettoyer les réseaux orphelins
docker network prune

Liens utiles

Résumé

  • Architecture multi-services avec Docker Compose
  • Reverse proxy Caddy pour le routage et SSL automatique
  • Frontend Nuxt avec build optimisé en production
  • Backend Symfony avec FrankenPHP pour les performances
  • Base de données PostgreSQL avec persistance
  • Services auxiliaires (Adminer, Mailpit, Gotenberg)
  • Configuration séparée pour dev/prod/review
  • Commandes Makefile pour simplifier l'utilisation
  • Healthchecks et monitoring intégrés