Docker et PHP, c'est une histoire d'amour compliquée. Des Dockerfiles de 200 lignes, des problèmes de permissions, des performances catastrophiques sur macOS. Si tu as déjà perdu une demi-journée à debugger un container PHP-FPM, cet article est pour toi. On va monter un setup complet et testé pour le développement Symfony.
Le docker-compose.yml complet
Voici le fichier docker-compose qui fonctionne en production chez nos clients. Il couvre les quatre services essentiels : PostgreSQL, Redis, PHP-FPM et Nginx.
version: '3.8'
services:
php:
build:
context: .
dockerfile: docker/php/Dockerfile
target: dev
volumes:
- .:/app:cached
- php_socket:/var/run/php
environment:
APP_ENV: dev
DATABASE_URL: postgresql://app:secret@postgres:5432/app
REDIS_URL: redis://redis:6379
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nginx:
image: nginx:1.25-alpine
ports:
- "8080:80"
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./public:/app/public:ro
- php_socket:/var/run/php
depends_on:
- php
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
redis_data:
php_socket:Le Dockerfile multi-stage : dev vs prod
Un seul Dockerfile avec deux targets. Le stage dev inclut Xdebug et Composer. Le stage prod est optimisé pour la performance avec OPcache.
# docker/php/Dockerfile
FROM php:8.3-fpm-alpine AS base
RUN apk add --no-cache \
icu-dev \
libpq-dev \
linux-headers \
&& docker-php-ext-install \
intl \
pdo_pgsql \
opcache
RUN apk add --no-cache libzip-dev \
&& docker-php-ext-install zip
WORKDIR /app
# ── Stage dev ──
FROM base AS dev
RUN apk add --no-cache $PHPIZE_DEPS \
&& pecl install xdebug redis \
&& docker-php-ext-enable xdebug redis
COPY docker/php/conf.d/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
COPY docker/php/conf.d/php-dev.ini /usr/local/etc/php/conf.d/php.ini
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# ── Stage prod ──
FROM base AS prod
RUN apk add --no-cache $PHPIZE_DEPS \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& apk del $PHPIZE_DEPS
COPY docker/php/conf.d/php-prod.ini /usr/local/etc/php/conf.d/php.ini
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritativeLa configuration Nginx pour PHP-FPM
# docker/nginx/default.conf
server {
listen 80;
server_name localhost;
root /app/public;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php-fpm.sock;
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;
}
}Les pièges courants et leurs solutions
Envie d'aller plus loin ?
Réserver un appel découverte →Après avoir mis en place Docker sur des dizaines de projets Symfony, voici les trois problèmes les plus fréquents.
1. Permissions fichiers — Le classique : les fichiers créés par le container appartiennent à root. La solution : ajouter un utilisateur non-root dans le Dockerfile avec le même UID que ton utilisateur local. ARG UID=1000 puis RUN adduser -D -u $UID appuser.
2. Performance sur macOS — Les volumes montés sont lents sur macOS à cause de la couche de virtualisation. Deux solutions : utiliser le flag :cached sur les volumes (déjà dans notre compose) ou exclure vendor/ du montage et l'installer directement dans le container.
3. Configuration Xdebug — Xdebug doit contacter ton IDE, pas l'inverse. La configuration critique :
; docker/php/conf.d/xdebug.ini
[xdebug]
xdebug.mode=debug
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.start_with_request=trigger
xdebug.idekey=PHPSTORMLes commandes du quotidien
# Démarrer l'environnement
docker compose up -d
# Exécuter les commandes Symfony
docker compose exec php bin/console cache:clear
docker compose exec php bin/console doctrine:migrations:migrate
# Lancer les tests
docker compose exec php vendor/bin/phpunit
# Lancer PHPStan
docker compose exec php vendor/bin/phpstan analyse --level=max
# Installer les dépendances
docker compose exec php composer install
# Arrêter et nettoyer
docker compose down -vCe setup couvre 90 % des besoins d'un projet Symfony. Pour les cas plus avancés — Elasticsearch, RabbitMQ, workers Messenger — il suffit d'ajouter les services dans le compose. Si tu cherches un accompagnement complet, notre offre Bear MVP inclut la configuration Docker dans chaque livraison de MVP.
Envie d'aller plus loin ?
Discutons de votre projet et voyons comment je peux vous aider.