Chapitre 740 min1 exercice
Laravel sous Docker
Tu as toutes les briques. Assemble-les pour une API Laravel : un serveur web, PHP, une base de données et un cache, chacun dans son conteneur.
Le trajet d'une requête
PHP-FPM exécute le PHP mais ne sait pas parler HTTP. Nginx reçoit les requêtes et lui transmet celles qui concernent Laravel. D'où deux conteneurs pour l'application.
GET /api/users de bout en bout.Les fichiers
Le code Laravel vit dans api/, la configuration Docker dans docker/. Cette organisation te resservira au chapitre 9, quand le front Next.js arrivera à côté.
projet/
├── compose.yaml
├── docker/
│ ├── nginx/default.conf
│ └── php/Dockerfile
└── api/ ← le projet LaravelFROM php:8.4-fpm
# Installe les extensions PHP dont Laravel a besoin
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/local/bin/
RUN install-php-extensions pdo_pgsql redis intl zip bcmath opcache
# Composer, récupéré depuis son image officielle
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
ENV COMPOSER_HOME=/tmp/composer
# Aligne www-data sur ton utilisateur : fini les erreurs de permission sur storage/
ARG UID=1000
ARG GID=1000
RUN groupmod -o -g ${GID} www-data && usermod -o -u ${UID} -g www-data www-data
WORKDIR /var/www/html
USER www-dataserver {
listen 80;
root /var/www/html/public;
index index.php;
client_max_body_size 20M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}root pointe vers public/, et fastcgi_pass php:9000 désigne le service php par son nom. Tu reconnais le réseau du chapitre 5.
services:
nginx:
image: nginx:stable-alpine
ports:
- "8000:80"
volumes:
- ./api:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
php:
build:
context: ./docker/php
args:
UID: ${UID:-1000}
GID: ${GID:-1000}
volumes:
- ./api:/var/www/html
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:18
environment:
POSTGRES_DB: laravel
POSTGRES_USER: laravel
POSTGRES_PASSWORD: ${DB_PASSWORD:-secret}
volumes:
- db-data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U laravel -d laravel"]
interval: 5s
timeout: 3s
retries: 10
redis:
image: redis:8-alpine
volumes:
db-data:Premier lancement
Nouveau projet
Pas besoin de PHP sur ta machine : Composer tourne dans un conteneur jetable.
mkdir projet && cd projet
docker run --rm --user "$(id -u):$(id -g)" -e COMPOSER_HOME=/tmp/composer \
-v "$PWD":/app -w /app composer:2 create-project laravel/laravel apiCrée les fichiers de la section précédente, puis remplace les lignes de base de données dans api/.env :
DB_CONNECTION=pgsql
DB_HOST=db
DB_PORT=5432
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
REDIS_HOST=redisdocker compose up -d --build
docker compose exec php php artisan migrateOuvre localhost:8000 : la page d'accueil de Laravel s'affiche.
Projet existant de l'équipe
git clone <url-du-depot> projet && cd projet
cp api/.env.example api/.env
docker compose up -d --build
docker compose exec php composer install
docker compose exec php php artisan key:generate
docker compose exec php php artisan migrate --seedAu quotidien
Toutes les commandes PHP passent par docker compose exec php. Ajoute ces alias à ton ~/.zshrc ou ~/.bashrc pour taper moins.
alias dc="docker compose"
alias art="docker compose exec php php artisan"
alias dcomposer="docker compose exec php composer"art make:model Invoice -mc # modèle, migration, contrôleur
art migrate
art tinker
art test
dcomposer require laravel/sanctum
dc logs -f php # erreurs PHP-FPM
dc exec php tail -f storage/logs/laravel.logEt Vite ?
Si le projet utilise des vues Blade avec Vite, ajoute un service Node dans compose.yaml. Pour une API pure consommée par Next.js, tu n'en as pas besoin.
vite:
image: node:24-slim
user: "${UID:-1000}:${GID:-1000}"
working_dir: /var/www/html
environment:
npm_config_cache: /tmp/npm
command: sh -c "npm install && npm run dev -- --host"
ports:
- "5173:5173"
volumes:
- ./api:/var/www/htmlexport default defineConfig({
server: {
host: true,
hmr: { host: "localhost" },
},
// plugins: [laravel(...)]
});Une API Laravel qui parle à PostgreSQL
- Crée un nouveau projet Laravel dans
projet/apiavec le conteneur Composer. - Ajoute
compose.yaml, le Dockerfile PHP et la configuration nginx de ce chapitre. - Configure
api/.envpour PostgreSQL et Redis, démarre la stack et lance les migrations. - Ajoute une route
/pingqui renvoie la version de PHP, le nom de la base et la réponse de Redis.
Ce que tu dois obtenir
curl localhost:8000/ping renvoie quelque chose comme {"php":"8.4.12","db":"laravel","redis":"ok"}. Si la base ou Redis ne répondent pas, Laravel affiche une erreur explicite.
Un indice
Dans routes/web.php, une closure suffit. DB::selectOne("select current_database() as name") interroge la base, Redis::ping() interroge Redis.
Erreur Permission denied sur storage/ ? Vérifie ton id -u et reconstruis l'image php.
Voir la solution
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
Route::get('/ping', fn () => [
'php' => PHP_VERSION,
'db' => DB::selectOne('select current_database() as name')->name,
'redis' => Redis::ping() ? 'ok' : 'ko',
]);docker compose up -d --build
docker compose exec php php artisan migrate
curl localhost:8000/ping