Nouveau projet Symfony 7. Stack cible : PostgreSQL 16, Redis 7, Apache (pas Nginx — préférence personnelle, on y reviendra). Environnement de dev : WSL2 sous Windows. En théorie, Docker + WSL2 c'est fluide depuis quelques versions.
En pratique, il y a 3 problèmes qui arrivent systématiquement le premier jour, qui ne sont pas documentés ensemble, et qui font perdre une heure à chaque fois. Voilà comment les éviter.
Le stack final
Le docker-compose.yml complet :
services:
app:
build: .
ports:
- "8080:80"
volumes:
- .:/var/www/html
depends_on:
- db
- redis
environment:
DATABASE_URL: "postgresql://app:password@db:5432/touspourris"
db:
image: postgres:16-alpine
ports:
- "5433:5432" # 5433 en local, pas 5432
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: password
POSTGRES_DB: touspourris
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Le détail qui compte : le port 5433:5432 pour PostgreSQL. C'est le cœur du
premier problème.
Problème 1 — Le conflit de port PostgreSQL
Si tu as PostgreSQL installé localement sur WSL2 — ce qui arrive souvent sur un poste de dev —
il écoute déjà sur le port 5432. docker compose up lance le container PostgreSQL
et essaie de binder 5432:5432 : conflit immédiat.
Error response from daemon: driver failed programming external connectivity on endpoint db:
Bind for 0.0.0.0:5432 failed: port is already allocated
Solution : mapper sur 5433 côté host (5433:5432 dans docker-compose.yml).
Le container continue d'écouter sur 5432 en interne — les autres services Docker le joignent
sans changer leur config. La variable DATABASE_URL pointe sur
db:5432, pas sur l'hôte. Seul le port exposé vers l'hôte change.
Pour se connecter depuis l'hôte (DBeaver, psql) : localhost:5433. C'est tout.
Problème 2 — Les permissions Docker group sous WSL2
Après installation de Docker Engine (pas Docker Desktop) :
sudo apt install docker.io
sudo usermod -aG docker $USER
Réflexe : lancer docker ps. Résultat :
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
La raison : usermod -aG docker $USER modifie le groupe pour les nouvelles
sessions, pas la session courante. Deux solutions :
# Option 1 : activer le groupe dans la session courante (temporaire)
newgrp docker
# Option 2 : redémarrer WSL2 entièrement (permanent)
# Dans PowerShell Windows :
wsl --shutdown
# Puis relancer WSL2
newgrp docker ouvre un sous-shell avec le nouveau groupe. Ça marche, mais
seulement pour le terminal courant. Le wsl --shutdown est la solution
définitive — WSL2 redémarre avec les groupes correctement appliqués.
Problème 3 — Docker daemon pas démarré au lancement WSL2
WSL2 ne lance pas systemd par défaut (ou selon les distros). Docker daemon ne tourne donc pas automatiquement au démarrage. Première commande Docker du matin :
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Deux solutions :
# Option 1 : démarrer manuellement à chaque fois
sudo service docker start
# Option 2 : activer systemd dans WSL2 (Ubuntu 22.04+)
# Dans /etc/wsl.conf :
[boot]
systemd=true
Avec systemd=true, Docker démarre automatiquement comme un service système.
C'est la solution propre si ta distro le supporte. Après modification de
/etc/wsl.conf, un wsl --shutdown depuis PowerShell pour que
le changement prenne effet.
Apache vs Nginx dans Docker
Choix délibéré d'Apache plutôt que Nginx pour le container app. Raison principale :
familiarité avec la config Apache pour du Symfony (.htaccess standard,
mod_rewrite activé). Nginx est souvent recommandé pour les perfs en prod,
mais en dev la différence est nulle et le coût de configuration supplémentaire n'est
pas justifié.
Le Dockerfile pour Symfony + Apache :
FROM php:8.3-apache
RUN apt-get update && apt-get install -y \
git zip unzip libpq-dev \
&& docker-php-ext-install pdo pdo_pgsql \
&& a2enmod rewrite
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY . .
RUN composer install --no-dev --optimize-autoloader
RUN chown -R www-data:www-data var/
L'extension pdo_pgsql est indispensable — sans elle, Doctrine lève une
exception au premier appel. a2enmod rewrite active le module Apache pour que
le routeur de Symfony fonctionne. Le chown final évite les erreurs de
permissions sur le cache et les logs.
Le Makefile comme interface unique
Avec Docker, les commandes deviennent longues. Un Makefile à la racine résout ça :
up:
docker compose up -d
down:
docker compose down
shell:
docker compose exec app bash
console:
docker compose exec app php bin/console $(cmd)
migrate:
docker compose exec app php bin/console doctrine:migrations:migrate --no-interaction
Usage : make up, make shell,
make console cmd="cache:clear". Tout le monde sur le projet utilise les
mêmes commandes sans connaître la syntaxe Docker exacte. Et les nouveaux arrivants
ont un point d'entrée documenté sans avoir à lire le docker-compose.yml en entier.
Conclusion
Les 3 problèmes — port conflict, group permissions, daemon startup — sont indépendants
mais arrivent tous le premier jour. Aucun n'est documenté dans les guides Docker officiels
pour WSL2. En les résolvant une fois proprement (5433 pour PG, wsl --shutdown,
systemd=true), le setup devient stable et reproductible.
Le reste — Symfony, PostgreSQL, Redis — fonctionne comme sur n'importe quel stack Docker standard. Le problème n'était pas Docker, c'était l'environnement WSL2 en dessous.