Aller au contenu

Symfony Docker

De Marmits Wiki

Docker avec les commandes composer, symfony et bin/console

Pour pouvoir exécuter des commandes composer, symfony et bin/console depuis votre machine locale tout en les faisant affecter le conteneur Docker, voici une approche optimale basée sur des volumes montés et des alias pratiques.



1. Montage des volumes pour synchroniser les fichiers

L’idée est de monter votre code local dans le conteneur pour que les modifications soient immédiatement visibles des deux côtés.

Solution 1 : Utilisation de docker-compose.yml (recommandé)

version: '3.8'

services:
  app:
    build: .
    volumes:
      - ./:/var/www/html  # Monte le projet Symfony (y compris vendor/)
      - ~/.composer:/tmp/composer  # Cache Composer (optionnel)
    working_dir: /var/www/html
    ports:
      - "8000:8000"  # Symfony CLI ou PHP-FPM
    tty: true
    stdin_open: true

Explications :

  • ./:/var/www/html : Synchronise le code local avec le conteneur (y compris vendor/).
  • ~/.composer:/tmp/composer : Cache Composer pour éviter de retélécharger les dépendances.
  • working_dir : S’assure que les commandes s’exécutent dans /var/www/html.



2. Exécuter des commandes dans le conteneur depuis l’hôte

Méthode 1 : docker-compose exec (pour les commandes ponctuelles)

# Commande Composer (ex: ajouter un bundle)
docker-compose exec app composer require mon/bundle-local

# Commande Symfony CLI (ex: lancer le serveur)
docker-compose exec app symfony serve -d

# Commande Console (ex: migrer la base)
docker-compose exec app php bin/console make:migration

Méthode 2 : Alias shell pour simplifier (dans ~/.bashrc ou ~/.zshrc)

# Alias pour Composer
alias dc-composer="docker-compose exec app composer"

# Alias pour Symfony CLI
alias dc-symfony="docker-compose exec app symfony"

# Alias pour la Console Symfony
alias dc-console="docker-compose exec app php bin/console"

Utilisation :

dc-composer require mon/bundle-local
dc-console make:migration
dc-symfony serve -d

3. Cas particulier : Développement d’un bundle local

Si vous développez un bundle en local et qu’il est lié via composer.json en "type": "path", assurez-vous que : 1. Le chemin est correct dans composer.json : json { "require": { "mon/bundle-local": "*", "symfony/framework-bundle": "^6.0" }, "repositories": [ { "type": "path", "url": "./packages/mon-bundle-local" } ] } 2. Le volume est bien monté dans docker-compose.yml : yaml volumes: - ./:/var/www/html - ./packages/mon-bundle-local:/var/www/html/packages/mon-bundle-local # Si le bundle est dans un sous-dossier 3. Reconstruire l’autoload après modification du bundle : bash docker-compose exec app composer dump-autoload



4. Optimisation pour le dev : Xdebug + volumes

Si vous utilisez Xdebug ou souhaitez un rechargement automatique :

# docker-compose.yml (extrait)
services:
  app:
    environment:
      XDEBUG_MODE: "develop,debug"
    volumes:
      - ./:/var/www/html
      - ~/.composer:/tmp/composer

Récapitulatif des bonnes pratiques

Besoin Solution
Exécuter composer docker-compose exec app composer require mon/bundle
Lancer bin/console docker-compose exec app php bin/console make:migration
Utiliser Symfony CLI docker-compose exec app symfony serve -d
Développer un bundle local Monter le dossier du bundle + composer dump-autoload après modification
Optimiser l’expérience dev Alias shell + volumes montés + Xdebug



Conclusion

  • Pour les commandes composer/symfony/console : Utilisez docker-compose exec.
  • Pour le dev de bundles locaux : Montez le dossier et utilisez composer dump-autoload.
  • Pour simplifier les commandes : Créez des alias (dc-composer, dc-console).

Cette approche permet un développement fluide sans avoir à reconstruire l’image à chaque modification. 🚀

composer dump-autoload

La commande composer dump-autoload est une commande essentielle dans l’écosystème PHP/Composer. Elle régénère le fichier d’autoloading (chargement automatique des classes) sans réinstaller les dépendances. Voici ce qu’elle fait en détail :



À quoi sert composer dump-autoload ?

  1. Reconstruit l’autoloader de Composer
    • Met à jour le fichier vendor/autoload.php qui gère le chargement automatique des classes PHP.
    • Utile quand vous ajoutez/modifiez des classes sans passer par composer install/update.
  2. Optimise les performances (si utilisé avec -o)
    • Avec l’option --optimize (-o), Composer génère une version optimisée de l’autoloader (classe map statique), ce qui accélère le chargement des classes en production :

      composer dump-autoload --optimize
      
  3. Prend en compte les classes dans autoload ou autoload-dev
    • Si vous avez des classes définies dans composer.json sous :

      "autoload": {
          "psr-4": { "MonApp\\": "src/" }
      }
      
    • La commande les intègre dans l’autoloader.



Quand l’utiliser ?

Cas d’usage Commande recommandée
Après avoir ajouté une nouvelle classe manuellement (sans Composer). composer dump-autoload
En production pour optimiser les performances. composer dump-autoload --optimize
Après avoir modifié composer.json (sans vouloir réinstaller les dépendances). composer dump-autoload
Pour vérifier les espaces de noms (PSR-4). composer dump-autoload



Différence avec composer install et composer update

  • composer install :

Installe les dépendances ET régénère l’autoloader.

  • composer update :

Met à jour les dépendances ET régénère l’autoloader.

  • composer dump-autoload :

Ne touche pas aux dépendances – ne fait que mettre à jour l’autoloader.



Exemple concret dans un projet Symfony

  1. Vous ajoutez une nouvelle entité src/Entity/Product.php :
    • Symfony utilise l’autoloading PSR-4, donc la classe sera automatiquement détectée.

    • Si elle n’est pas reconnue, exécutez :

      composer dump-autoload
      
  2. Vous développez un bundle local (lié via "type": "path" dans composer.json) :
    • Après avoir modifié le bundle, pour que Symfony reconnaisse les nouvelles classes :

      composer dump-autoload
      



Bonnes pratiques

  • En développement :
    Utilisez composer dump-autoload après avoir ajouté des classes manuellement.

  • En production :
    Utilisez composer dump-autoload --optimize pour des performances optimales.

  • Avec Docker :
    Si vous montez un volume (./:/var/www/html), exécutez la commande dans le conteneur :

    docker-compose exec app composer dump-autoload
    



Résumé

composer dump-autoload est un outil léger pour rafraîchir l’autoloader sans toucher aux dépendances. Indispensable pour :
- Le développement de bundles locaux.
- L’ajout manuel de classes.
- L’optimisation en production.

Utilisez-la dès que vous rencontrez des erreurs du type :
> “Class ‘MonApp\Entity\Product’ not found”

🚀 Astuce : Combinez-la avec --optimize en prod pour un boost de performances !

Symfony cache et composer cache avec Docker :


1. Rôle du dossier /var/cache dans Symfony

Symfony utilise ce dossier pour : - Le cache applicatif (ex : compilation des templates Twig, cache des routes, annotations) - Le cache système (ex : fichiers de configuration compilés comme srcApp_KernelDevDebugContainer.php)

Problème avec Docker :
Par défaut, ce cache est régénéré à chaque démarrage du conteneur → ralentissements (surtout en dev).



2. Stratégies pour optimiser le cache avec Docker

A. Monter /var/cache en volume (pour le dev)

# docker-compose.yml
services:
  php:
    volumes:
      - ./var/cache:/var/www/html/var/cache  # Monte le cache Symfony

Avantages : - Le cache persiste entre les redémarrages du conteneur. - Meilleures performances en développement.

Inconvénients : - Peut causer des problèmes de permissions (solved avec chmod ou entrypoint.sh).



B. Utiliser un volume Docker nommé (prod + dev)

volumes:
  symfony_cache:  # Volume dédié pour le cache

services:
  php:
    volumes:
      - symfony_cache:/var/www/html/var/cache

Bonus : Ajoutez un entrypoint.sh pour fixer les permissions :

#!/bin/bash
set -e

# Fixe les permissions du cache
chown -R www-data:www-data /var/www/html/var

exec "$@"

C. Cache warming en production

Dans votre Dockerfile :

FROM composer AS builder
WORKDIR /app
COPY . .
RUN composer install --no-dev --optimize-autoloader

FROM php:8.2-fpm
COPY --from=builder /app /var/www/html
RUN php bin/console cache:warmup  #  Pré-chauffe le cache

3. Gestion des environnements

Environnement Recommandation
Développement Volume monté (./var/cache:/...) + chmod
Production Volume nommé + cache warming dans l’image
CI/CD Cache éphémère (pas de montage)



4. Exemple complet (docker-compose.yml)

version: '3.8'

volumes:
  symfony_cache:  # Pour le cache
  composer_cache: # Pour Composer

services:
  app:
    build: .
    volumes:
      - ./:/var/www/html
      - symfony_cache:/var/www/html/var/cache
      - composer_cache:/tmp/composer
    environment:
      APP_ENV: dev
      COMPOSER_CACHE_DIR: /tmp/composer

5. Bonnes pratiques

  1. En dev : Montez var/cache pour éviter de tout recompiler.

  2. En prod : Utilisez cache:warmup dans l’image + volume nommé.

  3. Permissions : Résolvez-les via entrypoint.sh ou docker-compose :

    user: "${UID:-1000}:${GID:-1000}"
    



Différence avec Composer Cache

Composer (~/.composer) Symfony (/var/cache)
Type Cache de dépendances Cache applicatif
Montage Toujours utile Surtout en dev
Prod Volume nommé recommandé Warming dans l’image + volume



Résumé

  • Oui, on peut appliquer le même principe de volume monté pour /var/cache.
  • Mais : Symfony a besoin d’une gestion plus active (warming, permissions).
  • Optimisez :
    • Dev → Volume monté + permissions
    • Prod → Cache warming + volumes nommés

Cela garantit des performances optimales dans tous les cas ! 🚀

Configuration Docker pour un projet Symfony 6 / PHP FPM / avec des bundles locaux

Voici une méthode complète pour configurer votre environnement Docker avec Symfony 6, PHP 8.2, Apache, PostgreSQL et la gestion des bundles locaux.

1. Structure recommandée

~/debian/projet/
├── app/                  # Votre projet Symfony principal
│   ├── src/
│   ├── vendor/
│   └── ...
├── Bundles/              # Vos bundles locaux
│   ├── bundlea/          # Bundle A
│   └── bundleb/          # Bundle B
├── docker/
│   ├── apache/
│   │   └── vhost.conf   # Configuration Apache
│   ├── php/
│   │   └── php.ini      # Configuration PHP
│   └── entrypoint.sh     # Script d'initialisation
├── Dockerfile            # Fichier de build
└── docker-compose.yml    # Configuration des services

2. Dockerfile

# Dockerfile
FROM php:8.2-fpm

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    libzip-dev \
    libpq-dev \
    unzip \
    libevent-dev \
    && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-install \
    pdo \
    pdo_pgsql \
    pgsql \
    mbstring \
    exif \
    pcntl \
    bcmath \
    gd \
    zip \
    sockets

# Install event extension
RUN pecl install event && docker-php-ext-enable event

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

# Set working directory
WORKDIR /var/www

# Copy entrypoint
COPY docker/entrypoint.sh /usr/local/bin/entrypoint
RUN chmod +x /usr/local/bin/entrypoint

ENTRYPOINT ["entrypoint"]

3. docker-compose.yml

version: '3.8'

services:
  php:
    build: .
    volumes:
      - ./app:/var/www
      - ./Bundles:/var/www/bundles
    environment:
      - DATABASE_URL=postgresql://symfony:ChangeMe@postgres:5432/app?serverVersion=15&charset=utf8
    depends_on:
      - postgres

  apache:
    image: httpd:2.4
    ports:
      - "8080:80"
    volumes:
      - ./app/public:/var/www/html
      - ./docker/apache/vhost.conf:/usr/local/apache2/conf/extra/httpd-vhosts.conf
    command: ["httpd-foreground"]
    depends_on:
      - php

  postgres:
    image: postgres:15
    environment:
      POSTGRES_USER: symfony
      POSTGRES_PASSWORD: ChangeMe
      POSTGRES_DB: app
    volumes:
      - postgres_data:/var/lib/postgresql/data


volumes:
  postgres_data:

3 bis. docker-compose.yml (option)

  # Optionnel: Composer en tant que service
  composer:
    image: composer:latest
    volumes:
      - ./app:/var/www
      - ./Bundles:/var/www/bundles
    working_dir: /var/www
    entrypoint: ['composer']

4. Configuration Apache (docker/apache/vhost.conf)

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /var/www/html

    <Directory /var/www/html>
        AllowOverride All
        Require all granted
    </Directory>

    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/var/www/public/$1
</VirtualHost>

5. Script entrypoint.sh

#!/bin/bash
set -e

# Installer les dépendances si le vendor n'existe pas
if [ ! -d "/var/www/vendor" ]; then
  cd /var/www
  composer install
fi

# Lancer PHP-FPM
exec docker-php-entrypoint "$@"

6. Configuration Composer dans votre projet Symfony

Dans votre app/composer.json, assurez-vous d’avoir:

{
  "repositories": [
    {
      "type": "path",
      "url": "../Bundles/bundlea",
      "options": {
        "symlink": true
      }
    },
    {
      "type": "path",
      "url": "../Bundles/bundleb",
      "options": {
        "symlink": true
      }
    }
  ]
}

7. Workflow recommandé

  1. Initialisation:

    docker-compose build
    docker-compose up -d
    
  2. Pour utiliser Composer:

    • Soit via le service Composer:

      docker-compose run --rm composer install
      docker-compose run --rm composer update
      
    • Soit en entrant dans le container PHP:

      docker-compose exec php bash
      composer install
      
  3. Configuration PHPStorm:

    • Configurer l’interpréteur PHP dans Settings > PHP
    • Ajouter les mappings de chemins:
      • /var/www./app
      • /var/www/bundles./Bundles
    • Configurer le serveur Apache dans Settings > PHP > Servers
      • Nom: Docker Apache
      • Host: localhost
      • Port: 8080
      • Debugger: Xdebug
      • Path mappings comme ci-dessus


8. Avantages de cette configuration

  1. Développement simultané:
    • Vos bundles locaux sont accessibles dans le container via /var/www/bundles
    • Les modifications sont immédiatement visibles dans les deux sens
  2. Performance:
    • Les dépendances sont installées dans le container
    • Les symlinks Composer fonctionnent correctement
  3. Flexibilité:
    • Vous pouvez utiliser Composer de plusieurs manières
    • Configuration facilement extensible

Cette configuration vous permettra de travailler efficacement avec PHPStorm tout en bénéficiant d’un environnement Docker isolé et reproductible.

Cette ligne est assez importante dans le contexte d’un Dockerfile et d’un script d’entrée (entrypoint). Je vais vous l’expliquer en détail :

Explication de exec docker-php-entrypoint "$@"

  1. exec :
    • En shell, la commande exec remplace le processus courant (le script entrypoint.sh) par le nouveau processus spécifié
    • Cela signifie que le processus PID 1 du container devient docker-php-entrypoint au lieu de entrypoint.sh
    • Avantages :
      • Évite d’avoir un processus shell inutile qui reste en vie
      • Permet de recevoir correctement les signaux système (comme SIGTERM)
  2. docker-php-entrypoint :
    • C’est le script d’entrée par défaut de l’image officielle PHP
    • Il est fourni par les mainteneurs de l’image Docker PHP
    • Son rôle principal est de :
      • Configurer certaines variables d’environnement
      • Préparer le runtime PHP
      • Finalement lancer PHP-FPM
  3. "$@" :
    • C’est une notation spéciale en shell qui signifie “tous les arguments passés au script”
    • Si vous lancez le container avec docker run votre-image php -v, alors "$@" contiendra php -v
    • Cela permet de transmettre tous les arguments au processus suivant


Pourquoi c’est important dans votre cas ?

Dans votre entrypoint.sh, vous faites d’abord :

# Vérifie si vendor existe, sinon installe les dépendances
if [ ! -d "/var/www/vendor" ]; then
  cd /var/www
  composer install
fi

Puis vous terminez avec :

# Passe le relais au entrypoint officiel PHP
exec docker-php-entrypoint "$@"

Cela signifie : 1. Votre script fait d’abord son travail personnalisé (vérifier/vendor et installer les dépendances si besoin) 2. Ensuite, il “passe la main” au processus PHP-FPM officiel, devenant ainsi le processus principal du container


Alternative sans exec

Si vous écriviez simplement :

docker-php-entrypoint "$@"

Au lieu de :

exec docker-php-entrypoint "$@"

Alors : - Le shell du script entrypoint.sh resterait en vie inutilement - Les signaux système ne seraient pas correctement transmis à PHP-FPM - Vous auriez un processus superflu dans votre container

En résumé

Cette ligne est une bonne pratique Docker qui permet : 1. D’exécuter votre logique personnalisée avant le démarrage 2. De transférer proprement l’exécution au processus principal 3. De garantir une gestion propre des processus et des signaux

C’est particulièrement important pour des services comme PHP-FPM qui doivent être le processus principal du container pour fonctionner correctement.