⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

Configuration du développement Laravel avec Docker Compose

Ce guide montre comment configurer un environnement de développement pour une application Laravel en utilisant Docker et Docker Compose. Il s'appuie sur l'image de production pour PHP-FPM et ajoute ensuite des fonctionnalités axées sur le développeur, comme Xdebug, pour simplifier le débogage. En basant le conteneur de développement sur une image de production connue, vous maintenez les deux environnements étroitement alignés.

Cette configuration inclut les services PHP-FPM, Nginx et PostgreSQL (bien que vous puissiez facilement remplacer PostgreSQL par une autre base de données, comme MySQL ou MariaDB). Tout s'exécute dans des conteneurs, vous pouvez donc développer de manière isolée sans modifier votre système hôte.

Note

Pour expérimenter avec une configuration prête à l'emploi, téléchargez le dépôt Exemples Docker Laravel. Il contient des configurations pré-configurées pour le développement et la production.

Structure du projet

mon-app-laravel/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── docker/
│   ├── common/
│   │   └── php-fpm/
│   │       └── Dockerfile
│   ├── development/
│   │   ├── php-fpm/
│   │   │   └── entrypoint.sh
│   │   ├── workspace/
│   │   │   └── Dockerfile
│   │   └── nginx
│   │       ├── Dockerfile
│   │       └── nginx.conf
│   └── production/
├── compose.dev.yaml
├── compose.prod.yaml
├── .dockerignore
├── .env
├── vendor/
├── ...

Cette disposition représente un projet Laravel typique, avec les configurations Docker stockées dans un répertoire docker unifié. Vous trouverez deux fichiers Compose — compose.dev.yaml (pour le développement) et compose.prod.yaml (pour la production) — pour garder vos environnements séparés et gérables.

L'environnement inclut un service workspace, un conteneur d'accompagnement pour des tâches comme la construction des ressources front-end, l'exécution des commandes Artisan, et d'autres outils CLI que votre projet pourrait nécessiter. Bien que ce conteneur supplémentaire puisse sembler inhabituel, c'est un modèle familier dans des solutions comme Laravel Sail et Laradock. Il inclut également Xdebug pour aider au débogage.

Créer un Dockerfile pour PHP-FPM

Ce Dockerfile étend l'image de production en installant Xdebug et en ajustant les permissions des utilisateurs pour faciliter le développement local. De cette façon, votre environnement de développement reste cohérent avec la production tout en offrant des fonctionnalités de débogage supplémentaires et un montage de fichiers amélioré.

# Construit une couche uniquement pour le développement par-dessus l'image de production
FROM production AS development

# Utiliser les ARG pour définir les variables d'environnement passées depuis la commande de construction Docker ou Docker Compose.
ARG XDEBUG_ENABLED=true
ARG XDEBUG_MODE=develop,coverage,debug,profile
ARG XDEBUG_HOST=host.docker.internal
ARG XDEBUG_IDE_KEY=DOCKER
ARG XDEBUG_LOG=/dev/stdout
ARG XDEBUG_LOG_LEVEL=0

USER root

# Configurer Xdebug s'il est activé
RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \
    pecl install xdebug && \
    docker-php-ext-enable xdebug && \
    echo "xdebug.mode=${XDEBUG_MODE}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.idekey=${XDEBUG_IDE_KEY}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.log=${XDEBUG_LOG}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.client_host=${XDEBUG_HOST}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
    echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
fi

# Ajouter des ARG pour synchroniser les permissions
ARG UID=1000
ARG GID=1000

# Créer un nouvel utilisateur avec l'UID et le GID spécifiés, en réutilisant un groupe existant si le GID existe
RUN if getent group ${GID}; then \
      group_name=$(getent group ${GID} | cut -d: -f1); \
      useradd -m -u ${UID} -g ${GID} -s /bin/bash www; \
    else \
      groupadd -g ${GID} www && \
      useradd -m -u ${UID} -g www -s /bin/bash www; \
      group_name=www; \
    fi

# Mettre à jour dynamiquement php-fpm pour utiliser le nouvel utilisateur et groupe
RUN sed -i "s/user = www-data/user = www/g" /usr/local/etc/php-fpm.d/www.conf && \
    sed -i "s/group = www-data/group = $group_name/g" /usr/local/etc/php-fpm.d/www.conf


# Définir le répertoire de travail
WORKDIR /var/www

# Copier le script d'entrée
COPY ./docker/development/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

# Revenir à l'utilisateur non privilégié pour exécuter l'application
USER www-data

# Changer la commande par défaut pour exécuter le script d'entrée
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

# Exposer le port 9000 et démarrer le serveur php-fpm
EXPOSE 9000
CMD ["php-fpm"]

Créer un Dockerfile pour l'espace de travail

Un conteneur d'espace de travail fournit un shell dédié pour la compilation des ressources, les commandes Artisan/Composer, et d'autres tâches CLI. Cette approche suit les modèles de Laravel Sail et Laradock, consolidant tous les outils de développement dans un seul conteneur pour plus de commodité.

# docker/development/workspace/Dockerfile
# Utiliser l'image officielle PHP CLI comme base
FROM php:8.4-cli

# Définir les variables d'environnement pour l'ID utilisateur et groupe
ARG UID=1000
ARG GID=1000
ARG NODE_VERSION=22.0.0

# Installer les dépendances système et les bibliothèques de construction
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    unzip \
    libpq-dev \
    libonig-dev \
    libssl-dev \
    libxml2-dev \
    libcurl4-openssl-dev \
    libicu-dev \
    libzip-dev \
    && docker-php-ext-install -j$(nproc) \
    pdo_mysql \
    pdo_pgsql \
    pgsql \
    opcache \
    intl \
    zip \
    bcmath \
    soap \
    && pecl install redis xdebug \
    && docker-php-ext-enable redis xdebug\
    && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
    && apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Utiliser ARG pour définir les variables d'environnement passées depuis la commande de construction Docker ou Docker Compose.
ARG XDEBUG_ENABLED
ARG XDEBUG_MODE
ARG XDEBUG_HOST
ARG XDEBUG_IDE_KEY
ARG XDEBUG_LOG
ARG XDEBUG_LOG_LEVEL

# Configurer Xdebug s'il est activé
RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \
    docker-php-ext-enable xdebug && \
    echo "xdebug.mode=${XDEBUG_MODE}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.idekey=${XDEBUG_IDE_KEY}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.log=${XDEBUG_LOG}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
    echo "xdebug.client_host=${XDEBUG_HOST}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
    echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
fi

# Si le groupe existe déjà, l'utiliser ; sinon, créer le groupe 'www'
RUN if getent group ${GID}; then \
      useradd -m -u ${UID} -g ${GID} -s /bin/bash www; \
    else \
      groupadd -g ${GID} www && \
      useradd -m -u ${UID} -g www -s /bin/bash www; \
    fi && \
    usermod -aG sudo www && \
    echo 'www ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

# Passer à l'utilisateur non-root pour installer NVM et Node.js
USER www

# Installer NVM (Node Version Manager) en tant qu'utilisateur www
RUN export NVM_DIR="$HOME/.nvm" && \
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash && \
    [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \
    nvm install ${NODE_VERSION} && \
    nvm alias default ${NODE_VERSION} && \
    nvm use default

# S'assurer que NVM est disponible pour tous les shells futurs
RUN echo 'export NVM_DIR="$HOME/.nvm"' >> /home/www/.bashrc && \
    echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> /home/www/.bashrc && \
    echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> /home/www/.bashrc

# Définir le répertoire de travail
WORKDIR /var/www

# Remplacer le point d'entrée pour éviter le point d'entrée php par défaut
ENTRYPOINT []

# Commande par défaut pour maintenir le conteneur en cours d'exécution
CMD ["bash"]
Note

Si vous préférez une approche un-service-par-conteneur, omettez simplement le conteneur d'espace de travail et exécutez des conteneurs séparés pour chaque tâche. Par exemple, vous pourriez utiliser un conteneur php-cli dédié pour vos scripts PHP, et un conteneur node pour gérer la construction des ressources.

Créer une configuration Docker Compose pour le développement

Voici le fichier compose.yaml pour configurer l'environnement de développement :

services:
  web:
    image: nginx:latest # Utilisation de l'image Nginx par défaut avec une configuration personnalisée.
    volumes:
      # Monter le code de l'application pour les mises à jour en direct
      - ./:/var/www
      # Monter le fichier de configuration Nginx
      - ./docker/development/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      # Mapper le port 80 à l'intérieur du conteneur au port spécifié par 'NGINX_PORT' sur la machine hôte
      - "80:80"
    environment:
      - NGINX_HOST=localhost
    networks:
      - laravel-development
    depends_on:
      php-fpm:
        condition: service_started # Attendre que php-fpm démarre

  php-fpm:
    # Pour le service php-fpm, nous utiliserons notre Dockerfile PHP-FPM commun avec la cible de développement
    build:
      context: .
      dockerfile: ./docker/common/php-fpm/Dockerfile
      target: development
      args:
        UID: ${UID:-1000}
        GID: ${GID:-1000}
        XDEBUG_ENABLED: ${XDEBUG_ENABLED:-true}
        XDEBUG_MODE: develop,coverage,debug,profile
        XDEBUG_HOST: ${XDEBUG_HOST:-host.docker.internal}
        XDEBUG_IDE_KEY: ${XDEBUG_IDE_KEY:-DOCKER}
        XDEBUG_LOG: /dev/stdout
        XDEBUG_LOG_LEVEL: 0
    env_file:
      # Load the environment variables from the Laravel application
      - .env
    user: "${UID:-1000}:${GID:-1000}"
    volumes:
      # Mount the application code for live updates
      - ./:/var/www
    networks:
      - laravel-development
    depends_on:
      postgres:
        condition: service_started # Wait for postgres to start

  workspace:
    # For the workspace service, we will also create a custom image to install and setup all the necessary stuff.
    build:
      context: .
      dockerfile: ./docker/development/workspace/Dockerfile
      args:
        UID: ${UID:-1000}
        GID: ${GID:-1000}
        XDEBUG_ENABLED: ${XDEBUG_ENABLED:-true}
        XDEBUG_MODE: develop,coverage,debug,profile
        XDEBUG_HOST: ${XDEBUG_HOST:-host.docker.internal}
        XDEBUG_IDE_KEY: ${XDEBUG_IDE_KEY:-DOCKER}
        XDEBUG_LOG: /dev/stdout
        XDEBUG_LOG_LEVEL: 0
    tty: true # Enables an interactive terminal
    stdin_open: true # Keeps standard input open for 'docker exec'
    env_file:
      - .env
    volumes:
      - ./:/var/www
    networks:
      - laravel-development

  postgres:
    image: postgres:16
    ports:
      - "${POSTGRES_PORT:-5432}:5432"
    environment:
      - POSTGRES_DB=app
      - POSTGRES_USER=laravel
      - POSTGRES_PASSWORD=secret
    volumes:
      - postgres-data-development:/var/lib/postgresql/data
    networks:
      - laravel-development

  redis:
    image: redis:alpine
    networks:
      - laravel-development

networks:
  laravel-development:

volumes:
  postgres-data-development:
Note

Ensure you have an .env file at the root of your Laravel project with the necessary configurations. You can use the .env.example file as a template.

Run your development environment

To start the development environment, use:

$ docker compose -f compose.dev.yaml up --build -d

Run this command to build and start the development environment in detached mode. When the containers finish initializing, visit http://localhost/ to see your Laravel app in action.

Summary

By building on top of the production image and adding debug tools like Xdebug, you create a Laravel development workflow that closely mirrors production. The optional workspace container simplifies tasks like asset building and running Artisan commands. If you prefer a separate container for every service (e.g., a dedicated php-cli and node container), you can skip the workspace approach. Either way, Docker Compose provides an efficient, consistent way to develop your Laravel project.