Docker¶
Primatch utilise Docker Compose avec 9 services pour l'environnement de développement.
Architecture des conteneurs¶
graph LR
A["Nginx :8010 / :8020"]
A -->|"FastCGI :9000"| B[API PHP-FPM]
A -->|"proxy :8000"| H[MkDocs]
C[Frontend :3010] -->|"appels API"| A
C -->|"WebSocket"| F[Soketi :8090]
B --> D[(PostgreSQL :5440)]
B --> E[(Redis :6385)]
B --> F
G[Queue Worker] --> D
G --> E
I[SonarQube :9000] --> D Pourquoi Nginx ?
PHP-FPM ne parle pas HTTP, il parle FastCGI. Nginx sert de traducteur HTTP ↔ FastCGI. Il sert aussi les fichiers statiques directement (CSS, JS, images) sans solliciter PHP.
Rôle de chaque service¶
| Service | Port exposé | Rôle |
|---|---|---|
| nginx | :8010 (API) :8020 (Docs) | Reverse proxy : HTTP ↔ FastCGI pour l'API, proxy MkDocs sur :8020 |
| api | interne :9000 | PHP-FPM 8.3 exécutant Laravel. Non exposé directement |
| frontend | :3010 | React + Vite dev server (HMR). Appels API → localhost:8010 |
| pgsql | :5440 | PostgreSQL 16 — base de données principale |
| redis | :6385 | Cache, sessions et file de jobs (queues) |
| soketi | :8090 | Serveur WebSocket compatible Pusher |
| queue | — | Worker Laravel pour les jobs asynchrones (healthcheck Redis, restart auto toutes les 5 min) |
| mkdocs | interne :8000 | mkdocs serve — proxifié par Nginx sur :8020, basic auth |
| sonarqube | :9000 | Analyse qualité code (profil quality, non démarré par défaut) |
| Service | Port exposé | Rôle |
|---|---|---|
| nginx | :8011 | Reverse proxy API uniquement (sans docs) |
| api | interne :9000 | PHP-FPM 8.3. Volumes limités à storage/app et logs |
| frontend | :3011 | Build statique servi par Nginx |
| pgsql | :5440 | PostgreSQL 16 |
| redis | :6385 | Cache, sessions, queues |
| soketi | :8090 | WebSockets |
| queue | — | Worker Laravel (healthcheck Redis, restart auto) |
| mkdocs | interne :8000 | mkdocs serve — proxifié par nginx-docs sur :8020 |
| nginx-docs | :8020 | Nginx dédié à la documentation avec basic auth |
Différences dev / prod¶
| Aspect | Dev | Prod |
|---|---|---|
| API port | :8010 | :8011 |
| Frontend port | :3010 | :3011 |
| Volumes API | Code monté (./api:/var/www) | Seuls storage/app et logs montés |
| Frontend build | Vite dev server (HMR) | Build statique servi par Nginx |
| MkDocs proxy | Même conteneur Nginx (port 8020) | Conteneur nginx-docs dédié (port 8020) |
| Health checks | Queue worker (Redis ping) | Oui, sur tous les services |
| Telescope / Debug | Activé | Désactivé |
Hot-reload MkDocs (dev)
mkdocs serve surveille les modifications de fichiers existants, mais ne détecte pas les nouveaux fichiers. Après avoir ajouté un fichier .md ou modifié mkdocs.yml, relancez make docs pour redémarrer le conteneur.
Volumes persistants¶
| Volume | Données |
|---|---|
pgsql-data | Base de données PostgreSQL |
redis-data | Données Redis |
sonarqube-data | Configuration SonarQube |
storage-app-data (prod) | Fichiers uploadés |
nginx-logs (prod) | Logs Nginx |
Commandes essentielles¶
# Démarrage / arrêt
make dev # Démarrer tous les services
make stop # Arrêter
make down # Arrêter + supprimer les conteneurs
make restart # Redémarrer
make logs # Voir les logs
make ps # État des services
# Shell
make shell-api # Bash dans le conteneur API
make shell-frontend # Bash dans le conteneur frontend
make shell-pgsql # PostgreSQL CLI
make tinker # Laravel Tinker REPL
Profils Docker Compose¶
Certains services utilisent des profils et ne démarrent pas par défaut :
| Service | Profil | Commande |
|---|---|---|
| SonarQube | quality | make sonar-up |
Les autres services (api, nginx, frontend, pgsql, redis, soketi, queue, mkdocs) démarrent automatiquement avec make dev.
Résilience du Queue Worker¶
Le worker queue traite les jobs asynchrones (emails OTP, Telescope, etc.). Plusieurs mécanismes évitent les blocages silencieux :
| Paramètre | Valeur | Effet |
|---|---|---|
--max-time=300 | 5 min | Le worker s'arrête et redémarre toutes les 5 min (Docker restart: unless-stopped) |
--max-jobs=500 | 500 jobs | Redémarre après 500 jobs pour éviter les fuites mémoire |
--memory=128 | 128 Mo | Redémarre si la mémoire dépasse 128 Mo |
--backoff=3 | 3 sec | Délai exponentiel entre les tentatives en cas d'échec |
--timeout=60 | 60 sec | Timeout par job (tuer un job bloqué après 1 min) |
--tries=3 | 3 tentatives | Nombre de tentatives avant de marquer un job comme échoué |
stop_grace_period | 10s | Docker tue le conteneur après 10s s'il ne s'arrête pas proprement |
Healthcheck Docker : toutes les 30s, le conteneur vérifie :
- Le processus
queue:workest en cours (pgrep) - Redis est joignable (
php artisan queue:health-check)
Si l'un des deux échoue 3 fois consécutives, Docker redémarre automatiquement le conteneur.
La connexion Redis est configurée avec read_timeout=60 pour détecter les déconnexions silencieuses plutôt que bloquer indéfiniment.
Toujours utiliser Docker
Ne pas installer PHP ou Node localement. Toutes les commandes backend et frontend doivent être exécutées dans les conteneurs Docker.
Exception : Playwright E2E tourne sur l'hôte.