Déployer Laravel en production : Docker, CapRover et GitOps
Déployer une application Laravel en production peut sembler complexe, surtout quand on veut éviter la commande php artisan serve qui n'est absolument pas adaptée à un environnement de production. Dans cet article, je vais vous présenter une solution moderne et sécurisée utilisant Docker et CapRover pour un déploiement automatisé avec GitOps.
Template prêt à l'emploi
J'ai créé un template complet avec la configuration Laravel + Inertia.js + Docker + CapRover. Clonez et déployez en quelques minutes !
Voir le Template💡 Cet article s'applique particulièrement aux applications Laravel avec Inertia.js, mais les principes restent valables pour toute application Laravel.
Pourquoi éviter php artisan serve en production ?
La commande php artisan serve est un serveur de développement léger, parfait pour tester votre application localement, mais totalement inadapté pour la production. Il ne gère pas la montée en charge, n'offre pas les optimisations nécessaires et présente des failles de sécurité importantes. En production, vous avez besoin d'un vrai serveur web comme Nginx ou Apache avec PHP-FPM.
Docker : La conteneurisation simplifiée
Docker emballe votre application Laravel avec toutes ses dépendances (PHP, serveur web, extensions) dans un seul conteneur. Cela garantit que votre app fonctionne de façon identique partout : sur votre machine, en staging, et en production. Fini les problèmes de 'ça marche sur ma machine' !
CapRover : Votre propre Heroku
CapRover transforme n'importe quel serveur en Platform-as-a-Service comme Heroku. Avec une belle interface web, vous pouvez déployer des applications, gérer les domaines, obtenir des certificats SSL automatiques, et tout surveiller en temps réel. C'est comme avoir votre propre Heroku, mais moins cher et avec un contrôle total !
Dockerfile prêt pour la production
Mon template inclut un Dockerfile multi-stage optimisé pour Laravel + Inertia.js avec build Node.js, PHP-FPM, serveur web Caddy, et toutes les extensions nécessaires.
Dockerfile
Voir sur GitHubARG PHP_VERSION=${PHP_VERSION:-8.3}
# Node.js build stage
FROM node:20-alpine AS node-build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM php:${PHP_VERSION}-fpm-alpine AS php-system-setup
# Install system dependencies
RUN apk add --no-cache dcron busybox-suid libcap curl zip unzip git
# Install PHP extensions
COPY --from=mlocati/php-extension-installer /usr/bin/install-php-extensions /usr/bin/
RUN install-php-extensions intl bcmath gd pdo_mysql pdo_pgsql opcache redis uuid exif pcntl zip curl json mbstring xml tokenizer ctype fileinfo
# Install supervisord implementation
COPY --from=ochinchina/supervisord:latest /usr/local/bin/supervisord /usr/local/bin/supervisord
# Install caddy
COPY --from=caddy:2.2.1 /usr/bin/caddy /usr/local/bin/caddy
RUN setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy
# Install composer
COPY --from=composer/composer:2 /usr/bin/composer /usr/local/bin/composer
FROM php-system-setup AS app-setup
# ... Complete configuration in the GitHub repository
Build multi-stage avec Node.js, PHP 8.3, serveur Caddy, et optimisations pour la production
Services additionnels avec CapRover
CapRover rend incroyablement facile l'ajout de services complémentaires à votre application Laravel. Tout se déploie en un clic depuis l'app store.
Bases de données
- • MySQL - Base de données relationnelle traditionnelle
- • PostgreSQL - Base de données relationnelle avancée
- • Redis - Cache et sessions
Outils de gestion
- • phpMyAdmin - Interface de gestion MySQL
- • Fider - Système de feedback utilisateur
Configuration Nginx : Critique pour Inertia.js
L'un des aspects les plus importants lors du déploiement de Laravel avec Inertia.js est de bien configurer Nginx. La limite de taille de body par défaut est bien trop faible pour les applications modernes, surtout celles utilisant Inertia.js qui peuvent envoyer des requêtes volumineuses.
⚠️ Configuration Critique
- • client_max_body_size 50M - Essentiel pour gérer les grosses requêtes Inertia.js (peut être réduit à 10M)
- • proxy_buffer_size 128k - Optimise le traitement des headers
- • proxy_buffers 4 256k - Améliore la gestion des réponses
Configuration Nginx Complète
<%
if (s.forceSsl) {
%>
server {
listen 80;
server_name <%-s.publicDomain%>;
# Used by Lets Encrypt
location /.well-known/acme-challenge/ {
root <%-s.staticWebRoot%>;
}
# Used by CapRover for health check
location /.well-known/captain-identifier {
root <%-s.staticWebRoot%>;
}
location / {
return 302 https://$http_host$request_uri;
}
}
<%
}
%>
server {
<%
if (!s.forceSsl) {
%>
listen 80;
<%
}
if (s.hasSsl) {
%>
listen 443 ssl http2;
ssl_certificate <%-s.crtPath%>;
ssl_certificate_key <%-s.keyPath%>;
<%
}
%>
client_max_body_size 100M;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
server_name <%-s.publicDomain%>;
# 127.0.0.11 is DNS set up by Docker, see:
# https://docs.docker.com/engine/userguide/networking/configure-dns/
# https://github.com/moby/moby/issues/20026
resolver 127.0.0.11 valid=10s;
# IMPORTANT!! If you are here from an old thread to set a custom port, you do not need to modify this port manually here!!
# Simply change the Container HTTP Port from the dashboard HTTP panel
set $upstream http://<%-s.localDomain%>:<%-s.containerHttpPort%>;
location / {
<%
if (s.httpBasicAuthPath) {
%>
auth_basic "Restricted Access";
auth_basic_user_file <%-s.httpBasicAuthPath%>;
<%
}
%>
proxy_pass $upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
<%
if (s.websocketSupport) {
%>
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
<%
}
%>
}
# Used by Lets Encrypt
location /.well-known/acme-challenge/ {
root <%-s.staticWebRoot%>;
}
# Used by CapRover for health check
location /.well-known/captain-identifier {
root <%-s.staticWebRoot%>;
}
error_page 502 /captain_502_custom_error_page.html;
location = /captain_502_custom_error_page.html {
root <%-s.customErrorPagesDirectory%>;
internal;
}
}
Configuration d'exemple - CapRover gère la plupart automatiquement
Déploiement automatique avec GitHub
CapRover peut automatiquement déployer votre application à chaque fois que vous poussez vers votre repository Git. Il suffit de fournir l'URL de votre repo et une clé SSH, et CapRover s'occupe du reste !
Configuration simple :
- 1Connecter votre repository GitHub à CapRover
- 2Ajouter une clé SSH de déploiement à votre repository
- 3Lier votre application CapRover à votre repository GitHub en utilisant les webhooks
- 4Chaque git push déclenche un déploiement automatique
Configuration CapRover
Cette image est la configuration de l'application CapRover pour GitOps. Elle est utilisée pour déployer l'application automatiquement lorsqu'un nouveau commit est poussé vers le repository. Faites bien attention à ne pas mettre https:// et .git. Également, il faut setup le token directement dans le repo, vous trouverez des tutos sur le web.

Conclusion
Cette méthode révolutionne le déploiement d'applications Laravel en production. Avec Docker et CapRover, vous obtenez un environnement sécurisé, évolutif et entièrement automatisé. Fini les déploiements manuels et les problèmes de 'ça marche sur ma machine' ! Le GitOps vous permet de vous concentrer sur le développement pendant que votre infrastructure se gère automatiquement. L'un des plus grands avantages de cette approche est la simplicité de réplication : il suffit de cloner votre repository et de redéployer en quelques clics, sans aucune configuration manuelle. Parfait pour créer des environnements de staging, de test, ou déployer sur plusieurs serveurs !
Prêt à démarrer votre projet ?
Maintenant que vous avez toutes les clés en main, contactez-moi pour discuter de votre projet.
Demander un devis