Skip to Content

Chapitre 3.2 — Docker & FrankenPHP

Partie 3 : Installation & environnement — Chapitre 2/5 Version de référence : Symfony 7.4, FrankenPHP, Docker Compose v2.

⏱️ TL;DR

  • Docker rend l’environnement reproductible et proche de la prod : PostgreSQL, mailer, cache tournent dans des conteneurs, sans rien salir sur votre machine.
  • Un projet Symfony moderne arrive avec un compose.yaml (via la recipe Flex docker) qui déclare au minimum une base PostgreSQL ; la Symfony CLI détecte ces services et injecte automatiquement DATABASE_URL.
  • FrankenPHP est un serveur applicatif moderne (écrit en Go) qui embarque PHP : image Docker officielle, HTTPS/HTTP3, et surtout le mode worker (l’app bootstrappée une fois) pour des perfs proches de Node.
  • Trois environnements possibles : CLI locale (le plus simple, solo), Docker (équipe, proche prod), FrankenPHP (binaire unique, perfs prod). On peut combiner : CLI locale + services Docker.
  • Recommandation pour ce cours : Symfony CLI en local + PostgreSQL via Docker. Le meilleur des deux mondes.

🎯 Objectifs

  • Comprendre ce que Docker apporte et lire un compose.yaml de projet Symfony.
  • Démarrer les services (base de données) en conteneur et les connecter automatiquement.
  • Savoir ce qu’est FrankenPHP et pourquoi il compte (mode worker).
  • Choisir l’environnement adapté à votre situation.

1. Pourquoi Docker (surtout pour un dev qui vient du JS)

Installer PostgreSQL, Redis, un serveur mail « en dur » sur sa machine est fastidieux et diverge de la prod. Docker empaquette chaque service dans un conteneur reproductible : vous décrivez l’infrastructure dans un fichier, docker compose up, et tout tourne — identique sur chaque machine et proche de la production.

💡 Pour un dev Next.js : c’est le même réflexe que « je lance ma base et mes dépendances via docker compose pendant que next dev tourne en local ». Rien de nouveau côté Docker ; seule change la nature de l’app (Symfony).

2. Le compose.yaml d’un projet Symfony

Quand vous installez le pack webapp (ou la recipe docker), Flex ajoute un compose.yaml à la racine, typiquement avec une base PostgreSQL :

# compose.yaml (généré par la recipe Flex — extrait) services: database: image: postgres:16-alpine environment: POSTGRES_DB: app POSTGRES_USER: app POSTGRES_PASSWORD: '!ChangeMe!' ports: - "5432" volumes: - database_data:/var/lib/postgresql/data volumes: database_data:

Souvent, un compose.override.yaml (spécifique dev) expose les ports et ajoute des services de dev comme Mailpit (un serveur SMTP de test avec interface web pour lire les e-mails envoyés).

Démarrer / arrêter :

docker compose up -d # démarre les services en arrière-plan docker compose ps # état des conteneurs docker compose down # arrête (garde les volumes/données) docker compose down -v # arrête ET supprime les données

3. La magie : la Symfony CLI branche tout

Voici pourquoi on combine CLI locale + Docker. Quand des services Docker tournent, la Symfony CLI les détecte et injecte les variables d’environnement correspondantes (DATABASE_URL, MAILER_DSN…) dans votre application — sans que vous ayez à les écrire dans .env.

docker compose up -d # PostgreSQL démarre dans Docker symfony serve -d # le serveur Symfony local détecte la base symfony var:export --multiline # voir les variables injectées (DATABASE_URL…)

Résultat : vous codez en PHP local (rapide, débogage simple), mais la base vit dans Docker (propre, jetable). C’est le confort maximal.

⚠️ Piège : si vous définissez DATABASE_URL « en dur » dans .env.local, elle prime sur celle injectée par la CLI, ce qui peut masquer le service Docker. En dev avec la CLI, laissez la CLI gérer l’injection ; ne fixez DATABASE_URL manuellement que si vous n’utilisez pas ce mécanisme.

4. FrankenPHP : le serveur applicatif moderne

FrankenPHP est un serveur web écrit en Go qui embarque PHP. Il apporte trois choses majeures :

  1. Un serveur prêt pour la prod avec HTTPS automatique, HTTP/2 et HTTP/3, compression, etc. — sans Nginx + PHP-FPM à assembler.
  2. Le mode worker : au lieu de redémarrer l’application PHP à chaque requête (modèle classique PHP-FPM), FrankenPHP bootstrappe Symfony une seule fois puis sert de nombreuses requêtes avec l’app déjà en mémoire → gros gain de perf (proche de Node). On l’active en Partie 15.
  3. Un déploiement en binaire unique ou une image Docker officielle.

Utilisation la plus simple, via Docker (image officielle) :

# Dockerfile — base FrankenPHP (aperçu ; version prod détaillée en Partie 15) FROM dunglas/frankenphp:1-php8.4 # extensions PHP nécessaires RUN install-php-extensions pdo_pgsql intl opcache COPY . /app WORKDIR /app RUN composer install --no-dev --optimize-autoloader

En dev, on peut aussi utiliser FrankenPHP, mais pour ce cours on privilégie symfony serve (plus simple à déboguer). FrankenPHP brillera surtout en production (Partie 15).

💡 Pour un dev Next.js : FrankenPHP en mode worker, c’est le passage du modèle « une requête = un process qui démarre puis meurt » (façon serverless/CGI) à un modèle « serveur long-running qui garde l’app chaude » (façon node server.js). D’où des perfs comparables. La différence : l’état reste isolé par requête même en worker (Symfony réinitialise ce qu’il faut), ce qui évite les fuites d’état.

5. Quel environnement choisir ?

SituationRecommandation
Solo, un seul projet, démarrer viteSymfony CLI locale + PostgreSQL en Docker
Équipe, besoin d’iso prod, plusieurs servicesDocker Compose (app + services conteneurisés)
Perfs prod, déploiement simpleFrankenPHP (dev possible, prod recommandée)
Windows sans WSL, éviter DockerCLI locale + PostgreSQL local ou SQLite pour débuter

Pour ce cours : on suppose Symfony CLI en local pour le code + PostgreSQL via Docker pour la base. Si vous ne voulez pas de Docker du tout, une base SQLite (un simple fichier) suffit pour démarrer — on l’indiquera au chapitre 3.5.

📚 Aller plus loin : frankenphp.dev  (le serveur et son mode worker) et la doc Symfony « Using Symfony with Docker  ». On revient sur FrankenPHP prod en Partie 15.

✏️ Exercices

Exercice 1. Vous voulez coder en PHP local mais avoir une base PostgreSQL jetable. Quelle est la marche à suivre, et comment l’app trouve-t-elle la base ?

✅ Solution

  1. Démarrer la base en conteneur : docker compose up -d (le compose.yaml déclare PostgreSQL).
  2. Lancer le serveur Symfony local : symfony serve -d. La Symfony CLI détecte le service Docker et injecte automatiquement DATABASE_URL dans l’app — pas besoin de l’écrire dans .env. On peut vérifier avec symfony var:export. On code en PHP local (rapide), la base vit dans Docker (propre et jetable).

Exercice 2. Qu’est-ce que le « mode worker » de FrankenPHP change par rapport au modèle PHP-FPM classique ?

✅ Solution

En PHP-FPM classique, l’application PHP est réinitialisée à chaque requête (bootstrap complet à chaque fois). En mode worker, FrankenPHP bootstrappe l’application une seule fois et la garde en mémoire pour servir de nombreuses requêtes, ce qui réduit fortement le coût par requête (perfs proches de Node). Symfony réinitialise l’état par requête pour éviter les fuites.

Exercice 3. docker compose down vs docker compose down -v : quelle différence, et laquelle risque de vous faire perdre vos données de dev ?

✅ Solution

docker compose down arrête et supprime les conteneurs mais conserve les volumes (donc les données PostgreSQL). docker compose down -v supprime aussi les volumesperte des données. C’est cette dernière qui réinitialise complètement la base (utile pour repartir de zéro, dangereux si vous vouliez garder vos données).

🧠 Quiz de révision

1. Quel intérêt principal de Docker en développement ?

Un environnement reproductible et proche de la prod : les services (base, mailer…) tournent en conteneurs isolés, identiques d’une machine à l’autre, sans installation « en dur ».

2. Comment la Symfony CLI connaît-elle l’URL de la base lancée par Docker ?

Elle détecte les services Docker en cours et injecte automatiquement les variables (DATABASE_URL, etc.) dans l’application, sans qu’on les écrive dans .env.

3. Qu’est-ce que FrankenPHP, en une phrase ?

Un serveur applicatif moderne écrit en Go qui embarque PHP, avec HTTPS/HTTP3 automatiques et un mode worker (app bootstrappée une fois) pour de hautes performances.

4. Quelle combinaison recommande ce cours pour développer ?

Symfony CLI en local (pour le code) + PostgreSQL via Docker (base jetable), avec injection automatique de DATABASE_URL par la CLI.

5. Peut-on développer sans Docker du tout ?

Oui : PostgreSQL installé localement, ou une base SQLite (un simple fichier) pour débuter. Docker n’est pas obligatoire, juste pratique.


Prochain chapitre : 3.3 — Créer le projet Symfonysymfony new, squelette minimal vs pack webapp, et Flex en action.