"Ça marche sur ma machine." Cette phrase, dans une équipe de développement, c'est presque une blague. Presque, parce qu'elle provoque de vraies catastrophes. L'app fonctionne parfaitement en local, puis part en production et refuse de démarrer. PHP 7.4 en local, PHP 8.2 en prod. MySQL 5.7 en local, MySQL 8.0 en prod. Ce genre d'incohérence m'a coûté des nuits entières de débogage.
Docker élimine ce problème. Voici comment dockeriser une application Laravel proprement.
Comprendre Docker en 2 minutes
Docker n'est pas une machine virtuelle. C'est un système de conteneurs légers qui empaquettent votre application avec exactement l'environnement dont elle a besoin : la bonne version de PHP, les bonnes extensions, les bonnes variables d'environnement. Pas plus, pas moins.
Les concepts clés :
- Image — un template immuable (ex : PHP 8.3 + extensions Laravel)
- Conteneur — une instance en cours d'exécution d'une image
- docker-compose — orchestration de plusieurs conteneurs (PHP + MySQL + Redis)
- Volume — persistance des données hors du conteneur
Le Dockerfile pour Laravel
Voici un Dockerfile de production optimisé pour Laravel 11 :
FROM php:8.3-fpm-alpine
# Extensions PHP nécessaires pour Laravel
RUN apk add --no-cache \
libpng-dev \
libjpeg-turbo-dev \
libwebp-dev \
libzip-dev \
oniguruma-dev \
&& docker-php-ext-install \
pdo_mysql \
mbstring \
zip \
gd \
opcache
# Installer Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
# Copier les fichiers de dépendances en premier (optimisation du cache Docker)
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts
# Copier le reste du code
COPY . .
# Permissions Laravel
RUN chown -R www-data:www-data storage bootstrap/cache \
&& chmod -R 775 storage bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
Le docker-compose.yml : orchestrer tout l'environnement
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: laravel_app
restart: unless-stopped
volumes:
- .:/var/www/html
- ./storage:/var/www/html/storage
networks:
- laravel
depends_on:
- db
- redis
nginx:
image: nginx:alpine
container_name: laravel_nginx
restart: unless-stopped
ports:
- "80:80"
volumes:
- .:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks:
- laravel
depends_on:
- app
db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
networks:
- laravel
redis:
image: redis:alpine
container_name: laravel_redis
restart: unless-stopped
networks:
- laravel
networks:
laravel:
driver: bridge
volumes:
db_data:
La configuration Nginx
# docker/nginx/default.conf
server {
listen 80;
server_name localhost;
root /var/www/html/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Démarrer le projet en une commande
# Lancer tous les conteneurs en arrière-plan
docker-compose up -d
# Installer les dépendances Laravel
docker-compose exec app composer install
# Configurer l'application
docker-compose exec app php artisan key:generate
docker-compose exec app php artisan migrate --seed
# Voir les logs en temps réel
docker-compose logs -f app
Les avantages concrets pour votre workflow
- ✅ Onboarding en 5 minutes — un nouveau dev clone le repo, fait
docker-compose up, c'est prêt - ✅ Environnements identiques — dev, staging, production utilisent le même Dockerfile
- ✅ Isolation totale — chaque projet a ses propres versions de PHP et MySQL
- ✅ CI/CD simplifié — votre pipeline GitHub Actions utilise le même container
Conclusion
Adopter Docker pour vos projets Laravel n'est plus optionnel si vous travaillez en équipe ou si vous déployez régulièrement. L'investissement initial (une à deux heures pour tout configurer) est largement rentabilisé dès le premier problème d'environnement évité.
Et croyez-moi, un jour vous éviterez inévitablement cette nuit blanche à chercher pourquoi "ça marchait chez vous".