You are currently viewing Symfony et Docker : guide pour configurer votre projet

Symfony et Docker : guide pour configurer votre projet

  • Auteur/autrice de la publication :
  • Post category:DevOps

Dans cet article

  • Un projet symfony docker se lance en moins de 5 minutes avec la stack dunglas/symfony-docker
  • Le fichier docker-compose.yml orchestre au minimum 3 services : PHP, serveur web et base de données
  • FrankenPHP remplace avantageusement le duo PHP-FPM + Nginx avec un gain de 30 à 40 % en performances
  • La configuration multi-stage réduit la taille des images de production de 60 % en moyenne
  • L’intégration de MySQL ou PostgreSQL dans Docker élimine les conflits de versions entre développeurs
  • Le passage en production nécessite des ajustements sur les variables d’environnement, les volumes et le cache OPcache

Quand j’ai commencé à enseigner Symfony à mes étudiants en BTS SIO, la moitié du premier cours partait en configuration d’environnement. Chaque machine avait sa propre version de PHP, des extensions manquantes, un MySQL qui refusait de démarrer. Depuis que j’utilise symfony docker comme base de travail, ce problème a disparu. Chaque étudiant clone le dépôt, lance une commande, et tout fonctionne. Dans ce guide, je vous montre exactement comment reproduire cette configuration, que vous partiez de zéro ou que vous souhaitiez dockeriser un projet existant.

Pourquoi utiliser Docker avec Symfony

Docker résout un problème fondamental dans le développement Symfony : la cohérence des environnements. Sur un projet classique, le développeur A utilise PHP 8.3 sur macOS, le développeur B tourne sous PHP 8.2 sur Ubuntu, et le serveur de production fonctionne avec PHP 8.1 sous Debian. Les bugs liés à ces différences sont invisibles en local et explosent en production.

Avec Docker, vous définissez une seule configuration qui s’exécute de façon identique partout. Le fichier Dockerfile décrit précisément la version de PHP, les extensions installées, la configuration du serveur web. Le fichier docker-compose.yml orchestre tous les services : PHP, Nginx ou Apache, MySQL, Redis, Mailcatcher. Chaque membre de l’équipe travaille dans le même environnement, sans rien installer sur sa machine hôte en dehors de Docker lui-même.

L’écosystème Symfony a officiellement adopté Docker. Depuis Symfony 6.1, le composant symfony/runtime intègre un support natif de Docker via les variables d’environnement générées automatiquement. La documentation officielle recommande désormais Docker comme méthode d’installation privilégiée, ce qui facilite grandement la prise en main pour les débutants. Si vous découvrez Docker, je vous recommande de commencer par mon tutoriel Docker complet pour débutants avant de poursuivre ici.

Configuration docker-compose pour un projet Symfony avec services PHP et base de données
Configuration docker-compose pour un projet Symfony avec services PHP et base de données

Prérequis et outils nécessaires

Avant de lancer votre premier conteneur Symfony, vérifiez que votre poste de travail dispose des éléments suivants :

  • Docker Engine version 24 ou supérieure (vérifiez avec docker --version)
  • Docker Compose v2 (intégré à Docker Desktop, sinon installez le plugin docker-compose-plugin)
  • Git pour cloner les dépôts et gérer vos versions
  • Au moins 4 Go de RAM alloués à Docker (8 Go recommandés pour les projets avec Webpack Encore)
  • Un éditeur de code comme VS Code ou PhpStorm avec le plugin Docker

Vous n’avez pas besoin d’installer PHP, Composer, Symfony CLI ou MySQL sur votre machine. Tout sera conteneurisé. C’est justement l’intérêt de la démarche. Pour bien comprendre le fonctionnement des images que nous allons utiliser, consultez mon article sur les images Docker et leur utilisation.

Installer Symfony Docker avec la stack Dunglas

La méthode la plus rapide pour démarrer un projet Symfony avec Docker reste la stack officielle maintenue par Kévin Dunglas. Ce projet, hébergé sur le dépôt GitHub dunglas/symfony-docker, est recommandé par la core team Symfony et utilisé en production par des centaines d’entreprises.

Voici les commandes pour créer un nouveau projet :

# Cloner la stack
git clone https://github.com/dunglas/symfony-docker.git mon-projet
cd mon-projet

# Lancer la construction et le démarrage
docker compose build --no-cache
docker compose up -d

Au premier lancement, Docker télécharge les images de base, installe les dépendances Composer et génère un certificat TLS local. Le processus prend entre 2 et 5 minutes selon votre connexion. Une fois terminé, votre application est accessible à l’adresse https://localhost.

Cette stack inclut par défaut FrankenPHP comme serveur d’application, Composer pour la gestion des dépendances, et un support complet des workers Symfony Messenger. Elle génère automatiquement les variables DATABASE_URL et MAILER_DSN grâce à l’intégration Docker de Symfony.

Pour un projet existant, copiez simplement les fichiers compose.yaml, compose.override.yaml et le dossier frankenphp/ dans votre répertoire de travail, puis adaptez la configuration.

Configurer docker-compose manuellement

Si vous préférez maîtriser chaque composant ou si votre projet nécessite une architecture spécifique avec PHP-FPM et Apache ou Nginx, voici comment construire votre configuration pas à pas.

Commencez par le fichier Dockerfile pour le service PHP :

FROM php:8.3-fpm-alpine

# Extensions PHP nécessaires à Symfony
RUN apk add --no-cache \
    icu-dev \
    libzip-dev \
    && docker-php-ext-install \
    intl \
    pdo_mysql \
    zip \
    opcache

# Installation de Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

COPY . .

RUN composer install --no-dev --optimize-autoloader

EXPOSE 9000
CMD ["php-fpm"]

Ensuite, créez le fichier docker-compose.yml qui orchestre vos services :

version: '3.8'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./:/var/www/html
    depends_on:
      - database
    environment:
      DATABASE_URL: mysql://app:secret@database:3306/app_db?serverVersion=8.0

  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php

  database:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: app_db
      MYSQL_USER: app
      MYSQL_PASSWORD: secret
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "3306:3306"

volumes:
  db_data:

Il vous faut également le fichier de configuration Nginx (docker/nginx/default.conf) adapté à Symfony :

server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass php:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        internal;
    }

    location ~ \.php$ {
        return 404;
    }
}

Lancez ensuite docker compose up -d --build et accédez à http://localhost:8080. Cette configuration manuelle vous donne un contrôle total sur chaque brique de votre infrastructure.

Collaboration en équipe autour de la configuration Docker pour standardiser les environnements
Collaboration en équipe autour de la configuration Docker pour standardiser les environnements

Ajouter MySQL ou PostgreSQL à votre stack

La base de données est le service le plus critique de votre stack symfony docker. Voici un comparatif pour choisir entre MySQL et PostgreSQL :

Critère MySQL 8.0 PostgreSQL 16
Image Docker officielle mysql:8.0 (environ 580 Mo) postgres:16-alpine (environ 230 Mo)
Support Doctrine Natif, très répandu Natif, types avancés (JSON, arrays)
Performance lecture Excellent pour les requêtes simples Excellent pour les requêtes complexes
Extensions Symfony pdo_mysql pdo_pgsql
Réplication Docker Configuration manuelle Streaming replication intégrée
Idéal pour Projets classiques, CMS, e-commerce Projets avec données géospatiales, recherche full-text

Pour intégrer PostgreSQL à la place de MySQL, modifiez le service database dans votre docker-compose.yml :

  database:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: app_db
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

Adaptez ensuite le DATABASE_URL dans votre fichier .env :

DATABASE_URL="postgresql://app:secret@database:5432/app_db?serverVersion=16&charset=utf8"

Un point important : utilisez toujours un volume nommé pour persister les données de votre base. Sans volume, vous perdez toutes vos données à chaque docker compose down. C’est une erreur que je vois régulièrement chez mes étudiants, et elle peut coûter des heures de travail. Pour gérer vos données efficacement, pensez à bien structurer votre application selon les principes du développement web full stack.

FrankenPHP : l’alternative moderne à PHP-FPM

FrankenPHP est un serveur d’application PHP construit sur Caddy, créé par Kévin Dunglas. Il remplace à la fois PHP-FPM et Nginx en un seul binaire. L’avantage pour un projet Symfony est considérable : une image Docker plus légère, des performances supérieures et une configuration simplifiée.

Voici ce que FrankenPHP apporte concrètement :

  • Worker mode : l’application Symfony reste en mémoire entre les requêtes, éliminant le coût de bootstrap (gain de 30 à 40 % en temps de réponse)
  • HTTPS automatique : certificats Let’s Encrypt générés et renouvelés sans intervention
  • HTTP/3 et Early Hints (103) supportés nativement, améliorant le chargement des pages
  • Image unique : plus besoin de deux conteneurs PHP-FPM + Nginx

Le Dockerfile avec FrankenPHP est plus concis :

FROM dunglas/frankenphp:latest-php8.3-alpine

RUN install-php-extensions \
    intl \
    pdo_mysql \
    zip \
    opcache

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /app

COPY . .

RUN composer install --no-dev --optimize-autoloader

ENTRYPOINT ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]

La stack dunglas/symfony-docker utilise FrankenPHP par défaut depuis fin 2023. Si vous démarrez un nouveau projet, c’est la solution que je recommande. La documentation officielle Symfony sur Docker détaille les configurations avancées pour exploiter pleinement le worker mode.

Optimiser votre configuration pour la production

Passer de l’environnement de développement à la production nécessite plusieurs ajustements. La sécurité, les performances et la fiabilité deviennent prioritaires.

Build multi-stage

Le build multi-stage sépare les étapes de construction et d’exécution. Résultat : une image finale qui ne contient ni Composer, ni les dépendances de développement, ni le code source non compilé.

# Étape 1 : construction
FROM php:8.3-fpm-alpine AS builder
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --optimize-autoloader
COPY . .
RUN composer dump-autoload --optimize

# Étape 2 : image finale
FROM php:8.3-fpm-alpine
RUN docker-php-ext-install intl pdo_mysql opcache
COPY --from=builder /app /var/www/html
RUN chown -R www-data:www-data /var/www/html/var

Cette approche réduit la taille de l’image finale de 60 % en moyenne, passant souvent de 800 Mo à moins de 300 Mo.

Infrastructure serveur prête pour le déploiement en production d'une application Symfony conteneurisée
Infrastructure serveur prête pour le déploiement en production d’une application Symfony conteneurisée

Configuration OPcache

En production, OPcache doit être configuré de manière agressive. Ajoutez ces paramètres dans un fichier docker/php/opcache.ini :

opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.preload=/var/www/html/config/preload.php
opcache.preload_user=www-data

Le paramètre validate_timestamps=0 est essentiel en production : PHP ne vérifie plus si les fichiers ont changé sur le disque, ce qui améliore significativement les performances. En développement, laissez-le à 1 pour que vos modifications soient prises en compte immédiatement.

Variables d’environnement et secrets

Ne stockez jamais de secrets dans votre Dockerfile ou votre docker-compose.yml. Utilisez les Docker secrets ou un fichier .env.local monté en volume :

services:
  php:
    env_file:
      - .env.prod.local
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

La sécurité informatique est un sujet que je prends très au sérieux. Assurez-vous que vos fichiers de secrets sont dans votre .gitignore et jamais commités dans votre dépôt.

Health checks

Ajoutez des vérifications de santé à vos services pour que Docker redémarre automatiquement les conteneurs défaillants :

  php:
    healthcheck:
      test: ["CMD", "php-fpm-healthcheck"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

Erreurs fréquentes et solutions

Après plusieurs années à accompagner des développeurs dans leur découverte de symfony docker, voici les problèmes que je rencontre le plus souvent et leurs solutions :

Erreur Cause probable Solution
Permission denied sur var/cache UID/GID différents entre le conteneur et l’hôte Ajoutez user: "${UID}:${GID}" dans le service PHP du compose
Connection refused sur port 3306 Le service database n’est pas prêt Utilisez depends_on avec la condition service_healthy
Composer out of memory Limite mémoire PHP trop basse Ajoutez COMPOSER_MEMORY_LIMIT=-1 en variable d’environnement
Fichiers non synchronisés Volume mal configuré sur macOS/Windows Utilisez la synchronisation Mutagen ou les volumes natifs Docker Desktop
HTTPS non fonctionnel en local Certificat auto-signé non approuvé Installez le certificat CA avec docker compose exec php symfony server:ca:install
Extensions PHP manquantes Extensions non installées dans le Dockerfile Ajoutez l’extension avec docker-php-ext-install ou install-php-extensions

Un conseil que je donne systématiquement à mes étudiants : lisez les logs. La commande docker compose logs -f php affiche en temps réel tout ce qui se passe dans votre conteneur PHP. C’est la première chose à faire quand quelque chose ne fonctionne pas. Si vous êtes en formation et souhaitez approfondir ces compétences, renseignez-vous sur les formations informatiques à distance qui couvrent ces sujets.

Pour les problèmes de performances sur macOS, la lenteur des volumes montés est un problème connu. Depuis Docker Desktop 4.x, l’option VirtioFS améliore considérablement la vitesse de synchronisation des fichiers. Activez-la dans les préférences de Docker Desktop sous l’onglet « General ».

Si vous rencontrez des conflits de ports, vérifiez qu’aucun autre service n’utilise les ports 80, 443 ou 3306 sur votre machine hôte. Utilisez docker compose ps pour lister les conteneurs actifs et lsof -i :3306 pour identifier les processus occupant un port spécifique.

Pour aller plus loin dans la conteneurisation de vos applications, la maîtrise des outils de base du trio HTML, CSS et JavaScript reste indispensable pour bien structurer le frontend de vos projets Symfony. Le développement web sur mesure bénéficie énormément d’une infrastructure Docker bien pensée, car elle garantit la reproductibilité entre les environnements.

À retenir

  • Utilisez la stack dunglas/symfony-docker pour démarrer un projet en moins de 5 minutes avec une configuration éprouvée
  • Privilégiez FrankenPHP plutôt que PHP-FPM + Nginx pour simplifier votre stack et gagner en performances
  • Configurez un build multi-stage pour réduire la taille de vos images de production de 60 %
  • Utilisez toujours des volumes nommés pour vos bases de données afin d’éviter toute perte de données
  • Activez OPcache avec validate_timestamps=0 en production pour des performances optimales

Questions fréquentes


Comment installer Symfony avec Docker en une seule commande ?

Clonez la stack officielle avec git clone https://github.com/dunglas/symfony-docker.git mon-projet, puis lancez docker compose up -d depuis le dossier du projet. Docker construit automatiquement les images, installe les dépendances Composer et démarre le serveur. Votre application est accessible à l’adresse https://localhost en quelques minutes.

Faut-il utiliser MySQL ou PostgreSQL avec Symfony Docker ?

Les deux sont parfaitement supportés par Doctrine et fonctionnent très bien dans Docker. MySQL convient aux projets classiques (CMS, e-commerce) tandis que PostgreSQL excelle pour les requêtes complexes, les données JSON et la recherche full-text. L’image PostgreSQL Alpine est aussi plus légère (230 Mo contre 580 Mo pour MySQL). Choisissez en fonction de vos besoins métier.

Quelle est la différence entre FrankenPHP et PHP-FPM pour Symfony ?

FrankenPHP intègre un serveur web (Caddy) et PHP en un seul binaire, là où PHP-FPM nécessite un serveur web séparé comme Nginx ou Apache. FrankenPHP offre un worker mode qui garde l’application en mémoire entre les requêtes, réduisant le temps de réponse de 30 à 40 %. Il gère aussi automatiquement le HTTPS et supporte HTTP/3 nativement.

Comment résoudre les problèmes de permissions avec Docker et Symfony ?

Les erreurs de permission sur le dossier var/cache ou var/log proviennent d’une différence d’UID entre votre utilisateur hôte et l’utilisateur du conteneur. Ajoutez user: "${UID}:${GID}" dans votre service PHP du docker-compose.yml. Vous pouvez aussi exécuter chown -R www-data:www-data var/ dans le Dockerfile pour attribuer les bons droits au dossier var.

Comment optimiser les performances Docker pour Symfony sur macOS ?

Activez VirtioFS dans les préférences de Docker Desktop (onglet General) pour améliorer la vitesse de synchronisation des fichiers. Vous pouvez aussi utiliser Mutagen pour une synchronisation plus rapide des volumes. Enfin, excluez les dossiers vendor/ et var/ de la synchronisation en les plaçant dans des volumes nommés dédiés, ce qui réduit considérablement la latence.

Comment passer un projet Symfony Docker en production ?

Utilisez un build multi-stage pour réduire la taille de l’image. Désactivez le mode debug Symfony (APP_ENV=prod, APP_DEBUG=0). Configurez OPcache avec validate_timestamps=0 et activez le preloading. Stockez vos secrets via Docker secrets ou des fichiers .env.local montés en volume. Ajoutez des health checks à vos services pour garantir leur disponibilité.


Lucie Moreau
Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.

Lucie Moreau

Formatrice IT indépendante depuis 2016, ancienne étudiante BTS SIO SLAM. 6 ans d'expérience en entreprise.