Comment installer et configurer Laravel avec Docker Compose sur Ubuntu 22.04
Introduction
« Conteneuriser » une application fait référence au processus d'adaptation d'une application et de ses composants afin de pouvoir l'exécuter dans des environnements légers appelés conteneurs. Ces environnements sont isolés et jetables, et peuvent être utilisés pour le développement, les tests et le déploiement des applications en production.
Dans ce guide, nous utiliserons Docker Compose pour conteneuriser une application Laravel à des fins de développement. Une fois terminé, vous aurez une application Laravel de démonstration fonctionnant sur trois conteneurs de service distincts :
- Un service
appexécutant PHP7.4-FPM ; - Un service
dbexécutant MySQL 8.0 ; - Un service
nginxqui utilise le serviceapppour analyser le code PHP avant de servir l'application Laravel à l'utilisateur final.
Pour permettre un processus de développement simplifié et faciliter le débogage de l'application, nous garderons les fichiers de l'application synchronisés en utilisant des volumes partagés. Nous verrons également comment utiliser les commandes docker compose exec pour exécuter Composer et Artisan sur le conteneur app.
Déployez vos applications frontend depuis GitHub en utilisant la plateforme d'applications Linux-Console.net. Laissez Linux-Console.net se charger de la montée en charge de votre application.
Points clés à retenir :
- La conteneurisation rend le développement prévisible : Exécuter Laravel dans Docker garantit des environnements cohérents sur toutes les machines, éliminant les problèmes du type « ça fonctionne sur mon ordinateur » et facilitant la collaboration.
- La séparation des services améliore la maintenabilité : Séparer PHP, MySQL et Nginx dans des conteneurs distincts aide à isoler les problèmes, simplifie les mises à jour et reflète les configurations de production réelles.
- Les variables d'environnement sont au cœur d'une configuration flexible : L'utilisation d'un fichier
.envpermet aux développeurs de modifier les identifiants de la base de données et d'autres paramètres sans toucher au code de l'application. - Les images Docker personnalisées améliorent le contrôle et la sécurité : Construire votre propre image PHP vous permet d’installer uniquement ce dont votre projet a besoin, gardant ainsi l’environnement léger et sécurisé.
- Les permissions des fichiers doivent correspondre aux utilisateurs du conteneur : Définir la propriété et les permissions correctes pour les répertoires modifiables de Laravel empêche les erreurs à l'exécution et favorise un développement local fluide.
- L'utilisation de fichiers de remplacement prend en charge plusieurs environnements :
docker-compose.override.ymlpermet des ajustements locaux — comme le rechargement à chaud — sans modifier les configurations de production. Cela permet de garder le développement et le déploiement bien séparés. - Le dépannage commence par la compréhension du comportement des conteneurs : savoir comment consulter les journaux, vérifier les services en cours d'exécution et tester la connectivité est essentiel pour résoudre rapidement la plupart des problèmes dans des environnements conteneurisés.
- Une configuration basée sur Docker évolue avec votre flux de travail : Une fois construite, la même configuration peut alimenter les environnements locaux, de préproduction ou de production, créant ainsi une base stable et réutilisable pour les futurs projets Laravel.
Prérequis
- Accès à une machine locale Ubuntu ou à un serveur de développement en tant qu'utilisateur non root avec des privilèges sudo. Si vous utilisez un serveur distant, il est conseillé d'avoir un pare-feu actif installé. Pour configurer cela, veuillez vous référer à notre Guide de configuration initiale du serveur pour Ubuntu.
- Docker installé sur votre serveur, en suivant les étapes 1 et 2 de Comment installer et utiliser Docker sur Ubuntu.
- Docker Compose installé sur votre serveur, en suivant l'étape 1 de Comment installer et utiliser Docker Compose sur Ubuntu.
Étape 1 — Obtenir l’application de démonstration
Pour commencer, nous allons récupérer l'application Laravel de démonstration depuis son dépôt Github. Nous nous intéressons à la branche tutorial-01, qui contient l'application Laravel de base que nous avons créée dans le guide Comment installer et configurer Laravel avec Nginx sur Ubuntu 22.04 (LEMP).
Pour obtenir le code de l'application compatible avec ce tutoriel, téléchargez la version tutorial-1.0.1 dans votre répertoire personnel avec :
cd ~
curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zipNous aurons besoin de la commande unzip pour décompresser le code de l'application. Si vous n'avez pas encore installé ce paquet, faites-le maintenant avec :
sudo apt update
sudo apt install unzipMaintenant, décompressez le contenu de l'application et renommez le répertoire extrait pour y accéder plus facilement :
unzip travellist.zip
mv travellist-laravel-demo-tutorial-1.0.1 travellist-demoAccédez au répertoire travellist-demo :
cd travellist-demoÀ l'étape suivante, nous allons créer un fichier de configuration .env pour configurer l'application.
Étape 2 — Configuration du fichier .env de l’application
Les fichiers de configuration Laravel se trouvent dans un répertoire appelé config, à l’intérieur du répertoire racine de l’application. De plus, un fichier .env est utilisé pour configurer des paramètres dépendant de l’environnement, tels que les informations d’identification et toute information susceptible de varier entre les déploiements. Ce fichier n’est pas inclus dans le contrôle de version.
Avertissement : Le fichier de configuration de l’environnement contient des informations sensibles sur votre serveur, y compris les identifiants de base de données et les clés de sécurité. Pour cette raison, vous ne devriez jamais partager ce fichier publiquement.
Les valeurs contenues dans le fichier .env prévaudront sur les valeurs définies dans les fichiers de configuration habituels situés dans le répertoire config. Chaque installation sur un nouvel environnement nécessite un fichier d'environnement personnalisé pour définir des éléments tels que les paramètres de connexion à la base de données, les options de débogage, l'URL de l'application, ainsi que d'autres éléments pouvant varier selon l'environnement dans lequel l'application fonctionne.
Nous allons maintenant créer un nouveau fichier .env pour personnaliser les options de configuration de l'environnement de développement que nous sommes en train de mettre en place. Laravel est fourni avec un fichier exemple .env que nous pouvons copier pour créer le nôtre :
cp .env.example .envOuvrez ce fichier en utilisant nano ou l'éditeur de texte de votre choix :
nano .envLe fichier .env actuel de l'application de démonstration travellist contient des paramètres pour utiliser une base de données MySQL locale, avec 127.0.0.1 comme hôte de la base de données. Nous devons mettre à jour la variable DB_HOST afin qu'elle pointe vers le service de base de données que nous allons créer dans notre environnement Docker. Dans ce guide, nous appellerons notre service de base de données db. Allez-y et remplacez la valeur indiquée de DB_HOST par le nom du service de base de données :
APP_NAME=Travellist
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travellist
DB_USERNAME=travellist_user
DB_PASSWORD=password
...N’hésitez pas à modifier également le nom de la base de données, le nom d’utilisateur et le mot de passe, si vous le souhaitez. Ces variables seront utilisées à une étape ultérieure lorsque nous configurerons le fichier docker-compose.yml pour configurer nos services.
Enregistrez le fichier lorsque vous avez terminé de le modifier. Si vous avez utilisé nano, vous pouvez le faire en appuyant sur Ctrl+x, puis sur Y et Entrée pour confirmer.
Étape 3 : Configuration du Dockerfile de l’application
Bien que nos services MySQL et Nginx soient tous deux basés sur des images par défaut obtenues depuis Docker Hub, nous devons tout de même créer une image personnalisée pour le conteneur de l'application. Nous allons créer un nouveau Dockerfile à cet effet.
Notre image travellist sera basée sur l'image officielle PHP php:7.4-fpm de Docker Hub. Par-dessus cet environnement PHP-FPM de base, nous installerons quelques modules PHP supplémentaires ainsi que l'outil de gestion des dépendances Composer.
Nous allons également créer un nouvel utilisateur système ; cela est nécessaire pour exécuter les commandes artisan et composer lors du développement de l’application. Le paramètre uid garantit que l’utilisateur à l’intérieur du conteneur a le même uid que votre utilisateur système sur votre machine hôte, où vous exécutez Docker. Ainsi, tous les fichiers créés par ces commandes sont répliqués sur l’hôte avec les permissions correctes. Cela signifie également que vous pourrez utiliser votre éditeur de code préféré sur la machine hôte pour développer l’application qui s’exécute à l’intérieur des conteneurs.
Créer un nouveau Dockerfile avec :
nano DockerfileCopiez le contenu suivant dans votre Dockerfile :
FROM php:7.4-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www
USER $user
N’oubliez pas d’enregistrer le fichier lorsque vous avez terminé.
Notre Dockerfile commence par définir l'image de base que nous utilisons : php:7.4-fpm.
Après avoir installé les paquets système et les extensions PHP, nous installons Composer en copiant l'exécutable composer de sa dernière image officielle vers notre propre image d'application.
Un nouvel utilisateur du système est ensuite créé et configuré en utilisant les arguments user et uid qui ont été déclarés au début du Dockerfile. Ces valeurs seront injectées par Docker Compose au moment de la construction.
Enfin, nous définissons le répertoire de travail par défaut comme /var/www et passons à l'utilisateur nouvellement créé. Cela garantira que vous vous connectez en tant qu'utilisateur régulier et que vous êtes dans le bon répertoire lorsque vous exécutez les commandes composer et artisan sur le conteneur de l'application.
Étape 4 — Configuration de Nginx et fichiers de sauvegarde de la base de données
Lors de la création d'environnements de développement avec Docker Compose, il est souvent nécessaire de partager des fichiers de configuration ou d'initialisation avec les conteneurs de service afin de configurer ou d'initialiser ces services. Cette pratique facilite les modifications des fichiers de configuration pour ajuster votre environnement pendant le développement de l'application.
Nous allons maintenant créer un dossier avec des fichiers qui seront utilisés pour configurer et initialiser nos conteneurs de service.
Pour configurer Nginx, nous allons partager un fichier travellist.conf qui configurera la façon dont l'application est servie. Créez le dossier docker-compose/nginx avec :
mkdir -p docker-compose/nginxOuvrez un nouveau fichier nommé travellist.conf dans ce répertoire :
nano docker-compose/nginx/travellist.confCopiez la configuration Nginx suivante dans ce fichier :
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}Ce fichier configurera Nginx pour écouter sur le port 80 et utiliser index.php comme page d'index par défaut. Il définira la racine des documents sur /var/www/public, puis configurera Nginx pour utiliser le service app sur le port 9000 afin de traiter les fichiers *.php.
Enregistrez et fermez le fichier lorsque vous avez terminé de le modifier.
Pour configurer la base de données MySQL, nous partagerons un dump de la base de données qui sera importé lors de l'initialisation du conteneur. Il s'agit d'une fonctionnalité fournie par l'image MySQL 8.0 que nous utiliserons sur ce conteneur.
Créez un nouveau dossier pour vos fichiers d'initialisation MySQL à l'intérieur du dossier docker-compose :
mkdir docker-compose/mysqlOuvrez un nouveau fichier .sql :
nano docker-compose/mysql/init_db.sqlLe dump MySQL suivant est basé sur la base de données que nous avons configurée dans notre guide Laravel sur LEMP. Il créera une nouvelle table nommée places. Ensuite, il remplira la table avec un ensemble de lieux d'exemple.
Ajoutez le code suivant au fichier :
DROP TABLE IF EXISTS `places`;
CREATE TABLE `places` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`visited` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `places` (name, visited) VALUES ('Berlin',0),('Budapest',0),('Cincinnati',1),('Denver',0),('Helsinki',0),('Lisbon',0),('Moscow',1),('Nairobi',0),('Oslo',1),('Rio',0),('Tokyo',0);La table places contient trois champs : id, name et visited. Le champ visited est un indicateur utilisé pour identifier les endroits qui sont encore à visiter. N’hésitez pas à modifier les lieux d’exemple ou à en ajouter de nouveaux. Enregistrez et fermez le fichier une fois que vous avez terminé.
Nous avons terminé de configurer le Dockerfile de l’application et les fichiers de configuration des services. Ensuite, nous allons configurer Docker Compose pour utiliser ces fichiers lors de la création de nos services.
Étape 5 — Création d'un environnement multi-conteneurs avec Docker Compose
Docker Compose vous permet de créer des environnements multi-conteneurs pour les applications fonctionnant sur Docker. Il utilise des définitions de services pour construire des environnements entièrement personnalisables avec plusieurs conteneurs pouvant partager des réseaux et des volumes de données. Cela permet une intégration fluide entre les composants de l'application.
Pour configurer nos définitions de services, nous allons créer un nouveau fichier appelé docker-compose.yml. Généralement, ce fichier se trouve à la racine du dossier de l'application et il définit votre environnement conteneurisé, y compris les images de base que vous utiliserez pour construire vos conteneurs, ainsi que la manière dont vos services vont interagir.
Nous allons définir trois services différents dans notre fichier docker-compose.yml : app, db et nginx.
Le service app construira une image appelée travellist, basée sur le Dockerfile que nous avons créé précédemment. Le conteneur défini par ce service exécutera un serveur php-fpm pour analyser le code PHP et renvoyer les résultats au service nginx, qui fonctionnera sur un conteneur séparé. Le service mysql définit un conteneur exécutant un serveur MySQL 8.0. Nos services partageront un réseau pont nommé travellist.
Les fichiers de l'application seront synchronisés à la fois sur les services app et nginx via des bind mounts. Les bind mounts sont utiles dans les environnements de développement car ils permettent une synchronisation bidirectionnelle performante entre la machine hôte et les conteneurs.
Créez un nouveau fichier docker-compose.yml à la racine du dossier de l’application :
nano docker-compose.ymlUn fichier docker-compose.yml typique commence par une définition de version, suivie d'un nœud services, sous lequel tous les services sont définis. Les réseaux partagés sont généralement définis en bas de ce fichier.
Pour commencer, copiez ce code modèle dans votre fichier docker-compose.yml :
version: "3.9"
services:
networks:
travellist:
driver: bridgeNous allons maintenant modifier le nœud services pour inclure les services app, db et nginx.
Le service app
Le service app configurera un conteneur nommé travellist-app. Il construit une nouvelle image Docker basée sur un Dockerfile situé dans le même chemin que le fichier docker-compose.yml. La nouvelle image sera enregistrée localement sous le nom travellist.
Même si la racine du document servie comme application se trouve dans le conteneur nginx, nous avons également besoin des fichiers de l'application quelque part à l'intérieur du conteneur app, afin de pouvoir exécuter des tâches en ligne de commande avec l'outil Laravel Artisan.
Copiez la définition de service suivante sous votre nœud services, à l'intérieur du fichier docker-compose.yml :
app:
build:
args:
user: sammy
uid: 1000
context: ./
dockerfile: Dockerfile
image: travellist
container_name: travellist-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- travellistCes paramètres font ce qui suit :
build: Cette configuration indique à Docker Compose de construire une image locale pour le serviceapp, en utilisant le chemin spécifié (contexte) et le Dockerfile pour les instructions. Les argumentsuseretuidsont injectés dans le Dockerfile pour personnaliser les commandes de création d'utilisateur au moment de la construction.image: Le nom qui sera utilisé pour l'image en cours de création.container_name: Définit le nom du conteneur pour ce service.redémarrer: Toujours redémarrer, sauf si le service est arrêté.working_dir: Définit le répertoire par défaut pour ce service comme/var/www.volumes: Crée un volume partagé qui synchronisera le contenu du répertoire courant vers/var/wwwà l'intérieur du conteneur. Notez que ce n'est pas votre répertoire racine des documents, puisqu'il sera situé dans le conteneurnginx.réseaux: Configure ce service pour utiliser un réseau nommétravellist.
Le service db
Le service db utilise une image MySQL 8.0 préconstruite de Docker Hub. Comme Docker Compose charge automatiquement les fichiers de variables .env situés dans le même répertoire que le fichier docker-compose.yml, nous pouvons obtenir nos paramètres de base de données à partir du fichier .env de Laravel que nous avons créé à l'étape précédente.
Incluez la définition de service suivante dans votre nœud services, juste après le service app :
db:
image: mysql:8.0
container_name: travellist-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- travellistCes paramètres font ce qui suit :
image: Définit l’image Docker qui doit être utilisée pour ce conteneur. Dans ce cas, nous utilisons une image MySQL 8.0 provenant de Docker Hub.container_name: Configure le nom du conteneur pour ce service :travellist-db.redémarrer: Redémarrez toujours ce service, sauf s'il est explicitement arrêté.environment: Définit les variables d’environnement dans le nouveau conteneur. Nous utilisons les valeurs obtenues à partir du fichier.envde Laravel pour configurer notre service MySQL, qui créera automatiquement une nouvelle base de données et un nouvel utilisateur en fonction des variables d’environnement fournies.volumes: Crée un volume pour partager un fichier de vidage de base de données.sqlqui sera utilisé pour initialiser la base de données de l'application. L'image MySQL importera automatiquement les fichiers.sqlplacés dans le répertoire/docker-entrypoint-initdb.dà l'intérieur du conteneur.réseaux: Configure ce service pour utiliser un réseau nommétravellist.
Le service nginx
Le service nginx utilise une image Nginx préconstruite basée sur Alpine, une distribution Linux légère. Il crée un conteneur nommé travellist-nginx et utilise la définition ports pour créer une redirection du port 8000 sur le système hôte vers le port 80 à l'intérieur du conteneur.
Incluez la définition de service suivante dans votre nœud services, juste après le service db :
nginx:
image: nginx:1.17-alpine
container_name: travellist-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d
networks:
- travellistCes paramètres font ce qui suit :
image: Définit l'image Docker qui doit être utilisée pour ce conteneur. Dans ce cas, nous utilisons l'image Alpine Nginx 1.17.container_name: Configure le nom du conteneur pour ce service : travellist-nginx.restart: Redémarrez toujours ce service, sauf s'il est explicitement arrêté.ports: Configure une redirection de port qui permettra un accès externe via le port8000au serveur web fonctionnant sur le port80à l'intérieur du conteneur.volumes: Crée deux volumes partagés. Le premier synchronisera le contenu du répertoire actuel avec/var/wwwà l'intérieur du conteneur. Ainsi, lorsque vous apporterez des modifications locales aux fichiers de l'application, elles seront rapidement reflétées dans l'application servie par Nginx à l'intérieur du conteneur. Le deuxième volume s'assurera que notre fichier de configuration Nginx, situé àdocker-compose/nginx/travellist.conf, soit copié dans le dossier de configuration Nginx du conteneur.réseaux: Configure ce service pour utiliser un réseau nommétravellist.
Fichier docker-compose.yml terminé
Voici à quoi ressemble notre fichier docker-compose.yml final :
version: "3.9"
services:
app:
build:
args:
user: sammy
uid: 1000
context: ./
dockerfile: Dockerfile
image: travellist
container_name: travellist-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- travellist
db:
image: mysql:8.0
container_name: travellist-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- travellist
nginx:
image: nginx:1.17-alpine
container_name: travellist-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- travellist
networks:
travellist:
driver: bridgeAssurez-vous d'enregistrer le fichier lorsque vous avez terminé.
Étape 6 — Exécution de l'application avec Docker Compose
Nous allons maintenant utiliser les commandes docker compose pour créer l'image de l'application et exécuter les services que nous avons spécifiés dans notre configuration.
Construisez l'image app avec la commande suivante :
docker compose build appCette commande pourrait prendre quelques minutes à s'exécuter. Vous verrez une sortie similaire à ceci :
Building app
Sending build context to Docker daemon 377.3kB
Step 1/11 : FROM php:7.4-fpm
---> 8c08d993542f
Step 2/11 : ARG user
---> e3ce3af04d87
Step 3/11 : ARG uid
---> 30cb921ef7df
Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev libxml2-dev zip unzip
. . .
---> b6dbc7a02e95
Step 5/11 : RUN apt-get clean && rm -rf /var/lib/apt/lists/*
---> 10ef9dde45ad
. . .
Step 6/11 : RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
. . .
---> 920e4f09ec75
Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
---> dbbcd44e44af
Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user
---> db98e899a69a
Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user
---> 5119e26ebfea
Step 10/11 : WORKDIR /var/www
---> 699c491611c0
Step 11/11 : USER $user
---> cf250fe8f1af
Successfully built cf250fe8f1af
Successfully tagged travellist:latestUne fois la compilation terminée, vous pouvez exécuter l'environnement en mode arrière-plan avec :
docker compose up -dCreating travellist-db ... done
Creating travellist-app ... done
Creating travellist-nginx ... doneCela exécutera vos conteneurs en arrière-plan. Pour afficher des informations sur l'état de vos services actifs, exécutez :
docker compose psVous verrez une sortie comme ceci :
Name Command State Ports
-----------------------------------------------------------------------------------------------
travellist-app docker-php-entrypoint php-fpm Up 9000/tcp
travellist-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
travellist-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp,:::8000->80/tcpVotre environnement est maintenant opérationnel.
Vous pouvez maintenant vérifier que chaque service conteneurisé répond correctement en utilisant de simples commandes curl.
Pour tester le service web Nginx :
curl -I http://localhost:8000Résultat attendu :
HTTP/1.1 200 OK Server: nginx/1.17.10 Content-Type: text/html; charset=UTF-8Cela confirme que le conteneur Nginx fonctionne et sert des réponses depuis votre application Laravel.
Pour tester PHP-FPM via Nginx :
curl -s http://localhost:8000 | grep "Berlin"Si l'application fonctionne correctement, cette commande renvoie le code HTML de la page d'accueil qui inclut le mot Berlin.
Nous devons encore exécuter quelques commandes pour terminer la configuration de l'application. Vous pouvez utiliser la commande docker compose exec pour exécuter des commandes dans les conteneurs de service, comme un ls -l pour afficher des informations détaillées sur les fichiers dans le répertoire de l'application :
docker compose exec app ls -ltotal 256
-rw-r--r-- 1 sammy sammy 737 Apr 18 14:21 Dockerfile
-rw-r--r-- 1 sammy sammy 101 Jan 7 2020 README.md
drwxr-xr-x 6 sammy sammy 4096 Jan 7 2020 app
-rwxr-xr-x 1 sammy sammy 1686 Jan 7 2020 artisan
drwxr-xr-x 3 sammy sammy 4096 Jan 7 2020 bootstrap
-rw-r--r-- 1 sammy sammy 1501 Jan 7 2020 composer.json
-rw-r--r-- 1 sammy sammy 179071 Jan 7 2020 composer.lock
drwxr-xr-x 2 sammy sammy 4096 Jan 7 2020 config
drwxr-xr-x 5 sammy sammy 4096 Jan 7 2020 database
drwxr-xr-x 4 sammy sammy 4096 Apr 18 14:22 docker-compose
-rw-r--r-- 1 sammy sammy 1017 Apr 18 14:29 docker-compose.yml
-rw-r--r-- 1 sammy sammy 1013 Jan 7 2020 package.json
-rw-r--r-- 1 sammy sammy 1405 Jan 7 2020 phpunit.xml
drwxr-xr-x 2 sammy sammy 4096 Jan 7 2020 public
-rw-r--r-- 1 sammy sammy 273 Jan 7 2020 readme.md
drwxr-xr-x 6 sammy sammy 4096 Jan 7 2020 resources
drwxr-xr-x 2 sammy sammy 4096 Jan 7 2020 routes
-rw-r--r-- 1 sammy sammy 563 Jan 7 2020 server.php
drwxr-xr-x 5 sammy sammy 4096 Jan 7 2020 storage
drwxr-xr-x 4 sammy sammy 4096 Jan 7 2020 tests
-rw-r--r-- 1 sammy sammy 538 Jan 7 2020 webpack.mix.jsNous allons maintenant exécuter composer install pour installer les dépendances de l'application :
docker compose exec app rm -rf vendor composer.lock
docker compose exec app composer installVous verrez une sortie comme ceci :
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
. . .
Lock file operations: 89 installs, 0 updates, 0 removals
- Locking doctrine/inflector (2.0.4)
- Locking doctrine/instantiator (1.4.1)
- Locking doctrine/lexer (1.2.3)
- Locking dragonmantank/cron-expression (v2.3.1)
- Locking egulias/email-validator (2.1.25)
- Locking facade/flare-client-php (1.9.1)
- Locking facade/ignition (1.18.1)
- Locking facade/ignition-contracts (1.0.2)
- Locking fideloper/proxy (4.4.1)
- Locking filp/whoops (2.14.5)
. . .
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 89 installs, 0 updates, 0 removals
- Downloading doctrine/inflector (2.0.4)
- Downloading doctrine/lexer (1.2.3)
- Downloading dragonmantank/cron-expression (v2.3.1)
- Downloading symfony/polyfill-php80 (v1.25.0)
- Downloading symfony/polyfill-php72 (v1.25.0)
- Downloading symfony/polyfill-mbstring (v1.25.0)
- Downloading symfony/var-dumper (v4.4.39)
- Downloading symfony/deprecation-contracts (v2.5.1)
. . .
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.La dernière chose à faire avant de tester l'application est de générer une clé d'application unique avec l'outil en ligne de commande artisan de Laravel. Cette clé est utilisée pour chiffrer les sessions utilisateur et d'autres données sensibles :
docker compose exec app php artisan key:generateApplication key set successfully.Allez maintenant dans votre navigateur et accédez au nom de domaine ou à l'adresse IP de votre serveur sur le port 8000 :
http://server_domain_or_IP:8000Remarque : Si vous exécutez cette démo sur votre machine locale, utilisez http://localhost:8000 pour accéder à l'application depuis votre navigateur.
Vous verrez une page comme celle-ci :
Vous pouvez également tester l'application Laravel depuis l'intérieur du conteneur de l'application sans utiliser de navigateur :
docker compose exec app curl http://nginxSi tout est configuré correctement, vous devriez voir le code HTML de la page d'accueil par défaut de Laravel.
<html>
<head>
<title>Travel List</title>
</head>
<body>
<h1>My Travel Bucket List</h1>
<h2>Places I'd Like to Visit</h2>
<ul>
<li>Berlin</li>
<li>Budapest</li>
<li>Denver</li>
<li>Helsinki</li>
<li>Lisbon</li>
<li>Nairobi</li>
<li>Rio</li>
<li>Tokyo</li>
</ul>
<h2>Places I've Already Been To</h2>
<ul>
<li>Cincinnati</li>
<li>Moscow</li>
<li>Oslo</li>
</ul>
</body>
</html>Vous pouvez utiliser la commande logs pour vérifier les journaux générés par vos services :
docker compose logs nginxAttaching to travellist-nginx
. . .
travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:49:16 +0000] "GET / HTTP/1.1" 200 627 "-" "curl/7.82.0"
travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:51:27 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"
travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:51:27 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"Vous pouvez également utiliser la commande curl suivante pour déclencher des entrées de journal :
curl http://localhost:8000Puis relancez :
docker compose logs nginxVous devriez maintenant voir une entrée correspondante dans le journal d'accès pour votre requête.
Si vous voulez mettre en pause votre environnement Docker Compose tout en conservant l'état de tous ses services, exécutez :
docker compose pausePausing travellist-db ... done
Pausing travellist-nginx ... done
Pausing travellist-app ... doneVous pouvez ensuite reprendre vos services avec :
docker compose unpauseUnpausing travellist-app ... done
Unpausing travellist-nginx ... done
Unpausing travellist-db ... donePour arrêter votre environnement Docker Compose et supprimer tous ses conteneurs, réseaux et volumes, exécutez :
docker compose downStopping travellist-nginx ... done
Stopping travellist-db ... done
Stopping travellist-app ... done
Removing travellist-nginx ... done
Removing travellist-db ... done
Removing travellist-app ... done
Removing network travellist-laravel-demo_travellistPour un aperçu de toutes les commandes Docker Compose, veuillez consulter la référence des lignes de commande Docker Compose.
Correction des permissions des fichiers et répertoires Laravel
Lorsqu'on exécute Laravel à l'intérieur de conteneurs Docker, l'un des problèmes les plus courants auxquels les développeurs sont confrontés est lié aux permissions des fichiers et des répertoires. Laravel nécessite que certains répertoires soient modifiables par le processus PHP-FPM à l'intérieur du conteneur app. Si ces répertoires ne sont pas modifiables, l'application peut ne pas être en mesure d'enregistrer les erreurs, de mettre en cache les fichiers de configuration ou de stocker correctement les données de session.
Vous pourriez rencontrer des messages tels que :
The stream or file "/var/www/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission deniedou
file_put_contents(/var/www/bootstrap/cache/config.php): Failed to open stream: Permission deniedCes erreurs indiquent que l'utilisateur exécutant PHP dans le conteneur n'a pas la permission d'écrire dans les répertoires nécessaires.
Les étapes suivantes décrivent comment diagnostiquer et résoudre ces problèmes à la fois dans les environnements locaux et de production.
Ajuster les permissions du répertoire en écriture
Laravel nécessite que deux répertoires soient accessibles en écriture par l'utilisateur du serveur web :
/var/www/storage/var/www/bootstrap/cache
Si vous voyez des erreurs de permission, vous pouvez les corriger en ajustant la propriété et les permissions depuis l'intérieur du conteneur :
docker compose exec app chown -R sammy:sammy /var/www/storage /var/www/bootstrap/cache
docker compose exec app chmod -R 775 /var/www/storage /var/www/bootstrap/cacheSi votre Dockerfile utilise un nom d’utilisateur différent (défini via l’argument de construction user), remplacez sammy par ce nom d’utilisateur.
Vous pouvez vérifier la propriété avec la commande suivante :
docker compose exec app ls -ld /var/www/storage /var/www/bootstrap/cacheLa sortie devrait montrer que l’utilisateur et le groupe correspondent au processus PHP-FPM à l’intérieur du conteneur.
Si vous voulez plutôt ajuster les permissions depuis la machine hôte, exécutez :
sudo chown -R $(id -u):$(id -g) storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cacheCela garantit que les deux répertoires Laravel sont accessibles en écriture par le conteneur et par votre utilisateur hôte.
Définir la propriété du répertoire lors de la création de l'image
Pour éviter que les problèmes de permissions ne se reproduisent après chaque reconstruction, vous pouvez définir la propriété du répertoire lors du processus de création de l'image Docker. Ouvrez votre Dockerfile et ajoutez la ligne suivante vers la fin, avant de passer à l'utilisateur non root :
RUN chown -R $user:www-data /var/wwwCette commande garantit que tous les fichiers et répertoires sous /var/www appartiennent à l'utilisateur que vous avez défini dans votre Dockerfile.
Pour une approche plus ciblée et sécurisée, vous pouvez n'ajuster que les répertoires sur lesquels Laravel doit écrire :
RUN chown -R $user:www-data /var/www/storage /var/www/bootstrap/cacheAprès avoir effectué cette modification, reconstruisez l'image et redémarrez les conteneurs :
docker compose build app
docker compose up -dLa prochaine fois que le conteneur démarrera, il aura déjà les permissions correctes.
Vérifier la cohérence de l’ID utilisateur entre l’hôte et le conteneur
Lors de l'utilisation des montages bind, Docker partage des fichiers entre votre hôte et le conteneur. Si l'UID numérique de l'utilisateur de l'hôte diffère de l'UID défini dans le conteneur, des conflits de propriété des fichiers peuvent survenir. Cela est courant sur les systèmes où les identifiants d'utilisateurs varient d'une machine à l'autre.
Pour vérifier les valeurs UID, exécutez :
id -u $(whoami)
docker compose exec app id -uSi ces deux numéros ne correspondent pas, mettez à jour votre fichier docker-compose.yml pour transmettre votre UID réel au processus de construction :
build:
args:
user: sammy
uid: 1000Ensuite, reconstruisez l'image :
docker compose build app
docker compose up -dCela garantit que l'utilisateur du conteneur correspond à votre utilisateur hôte, évitant ainsi les problèmes de permissions sur les fichiers montés en liaison.
Corriger les permissions du répertoire de cache de Composer
Composer stocke les dépendances téléchargées et les fichiers cache dans le répertoire personnel de l’utilisateur à l’intérieur du conteneur (/home/sammy/.composer). Si ce répertoire n’est pas accessible en écriture, vous pourriez voir des avertissements tels que :
Cannot create cache directory /home/sammy/.composer/cacheVous pouvez résoudre ce problème en créant le répertoire de cache et en attribuant la propriété correcte :
docker compose exec app mkdir -p /home/sammy/.composer/cache
docker compose exec app chown -R sammy:sammy /home/sammy/.composerCela garantit que Composer peut stocker les dépendances et les fichiers en cache sans erreurs de permission, ce qui accélère également les futures exécutions de composer install.
Pratiques recommandées pour les environnements de production
En production, la gestion des permissions devrait être effectuée lors de la création de l'image plutôt qu'à l'exécution. Cela améliore la cohérence et la sécurité.
Suivez ces pratiques pour une configuration prête pour la production :
Évitez les montages bind pour le code de l'application : copiez plutôt les fichiers de l'application dans l'image lors de la construction. Les montages bind devraient être réservés au développement.
Définir les permissions pendant la construction : Ajoutez les commandes
RUN chownetchmodà votre Dockerfile pour garantir la propriété et les droits d'accès corrects avant le déploiement.Utilisez l’utilisateur avec les moindres privilèges : Assurez-vous que le processus PHP s’exécute sous un utilisateur non-root (la configuration actuelle avec
$userle fait déjà).Restreindre les permissions sur les répertoires non modifiables : La plupart des fichiers d'application devraient être en lecture seule. Vous pouvez appliquer cela avec :
chmod -R 755 /var/www chmod -R 775 /var/www/storage /var/www/bootstrap/cacheCette configuration permet à Laravel d'écrire uniquement là où c'est nécessaire tout en protégeant les autres fichiers de l'application contre toute modification.
En suivant ces étapes, vos conteneurs Laravel auront des permissions de fichiers stables et prévisibles, tant dans les environnements locaux que de production. Cela réduit les erreurs récurrentes et garantit que Laravel peut enregistrer des données, mettre en cache des fichiers et écrire des sessions de manière fiable.
Comprendre docker-compose.override.yml pour les environnements locaux et de production
Docker Compose vous permet de définir des applications multi-conteneurs à l'aide d'un seul fichier de configuration. Dans la plupart des cas, cette configuration est stockée dans un fichier nommé docker-compose.yml. Cependant, la gestion de multiples environnements, tels que le développement local et la production, nécessite souvent des ajustements spécifiques à l'environnement. C'est là qu'intervient le fichier docker-compose.override.yml.
Par défaut, Docker Compose recherche automatiquement un fichier nommé docker-compose.override.yml dans le même répertoire que le fichier Compose de base. Lorsqu’il est trouvé, il fusionne les configurations des deux fichiers lorsque vous exécutez une commande docker compose. Cette approche permet aux développeurs de maintenir une configuration de base propre et réutilisable tout en personnalisant certains aspects de la configuration pour une utilisation locale ou en production.
Le rôle de docker-compose.override.yml
Le fichier docker-compose.override.yml est une extension de la configuration Compose de base. Il modifie ou ajoute des propriétés qui ne s'appliquent qu'à un environnement particulier, sans nécessiter de modifications du fichier principal docker-compose.yml. Le fichier de substitution est particulièrement utile dans les flux de travail de développement local, où les développeurs ont souvent besoin de monter du code source, d'activer des outils de débogage ou de modifier des variables d'environnement pour les tests.
Lorsque vous exécutez la commande docker compose up, Docker fusionne automatiquement le contenu de docker-compose.yml et docker-compose.override.yml. Si un service, un volume ou une configuration est défini dans les deux fichiers, les valeurs du fichier de substitution priment.
Pour utiliser un fichier de substitution différent, par exemple, un destiné à la production, vous pouvez spécifier le fichier manuellement en utilisant le paramètre -f :
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dCette approche vous permet de maintenir des configurations séparées pour différents environnements tout en utilisant une structure de commande unique et cohérente.
Structuration pour le développement local
Les environnements de développement locaux nécessitent généralement des changements fréquents, un rechargement en direct du code et des journaux détaillés. Le fichier docker-compose.override.yml permet d'ajouter ces fonctionnalités sans affecter les autres environnements.
Un fichier de remplacement local typique peut inclure :
- Montages liés pour les mises à jour de code en direct
- Directives de construction locales au lieu d'utiliser des images préconstruites
- Variables d'environnement spécifiques au développement
- Services de débogage et de test
Par exemple :
version: "3.9"
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./src:/app
- ./logs:/app/logs
environment:
- DATABASE_URL=postgres://postgres:postgres@db:5432/app_db
- LOG_LEVEL=debug
ports:
- "8000:8000"
depends_on:
- db
db:
environment:
- POSTGRES_PASSWORD=postgresDans cet exemple :
- Le service
appest construit directement à partir d'un Dockerfile local (Dockerfile.dev), ce qui facilite le test des modifications sans avoir à reconstruire les images via un registre. - Le code source est monté à l'aide de montages bind, ce qui permet au conteneur de refléter les modifications des fichiers locaux en temps réel.
- Les variables d'environnement telles que
LOG_LEVEL=debugsont définies pour fournir des sorties plus détaillées pendant le développement. - La base de données utilise des identifiants simples qui conviennent pour des tests locaux, mais ne devraient pas être utilisés en production.
Cette configuration offre un environnement de développement plus rapide et plus flexible tout en conservant la configuration de base inchangée.
Préparation à la production
Les environnements de production exigent stabilité, reproductibilité et sécurité. Les conteneurs doivent être exécutés à partir d’images préconstruites plutôt que d’être construits localement, et les informations sensibles doivent être gérées de manière sécurisée. Contrairement au fichier de surcharge appliqué automatiquement pour le développement local, les surcharges de production doivent être spécifiées explicitement.
Un fichier de remplacement pour la production (docker-compose.prod.yml) est généralement conçu pour remplacer les étapes de construction locales par des références d'images, utiliser des volumes nommés plutôt que des montages de répertoires, et définir des propriétés liées au déploiement telles que les limites de ressources et la mise à l'échelle.
Exemple :
version: "3.9"
services:
app:
image: registry.example.com/myapp:1.2.3
environment:
- DATABASE_URL=${DATABASE_URL}
- LOG_LEVEL=info
volumes:
- app-data:/var/lib/app
ports:
- "8000:8000"
restart: unless-stopped
deploy:
replicas: 3
resources:
limits:
cpus: "0.5"
memory: 512M
db:
image: postgres:15
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
external: true
volumes:
app-data:
db-data:Dans cette configuration :
Le service
appfait référence à une image préconstruite (myapp:1.2.3) stockée dans un registre au lieu de la construire localement.Les montages liés sont remplacés par des volumes nommés afin d'assurer un stockage de données cohérent et isolé.
Les informations d'identification sensibles sont stockées de manière sécurisée à l'aide des secrets Docker.
La section
deploydéfinit le comportement de mise à l’échelle et les limites de ressources pour une meilleure stabilité sous charge.La configuration doit être appliquée explicitement lors du déploiement :
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Cette structure garantit que les déploiements en production sont cohérents, contrôlés et exempts d'artefacts issus du développement local.
Comparer les remplacements locaux et de production
| Aspect de configuration | Local (docker-compose.override.yml) | Production (docker-compose.prod.yml) |
|---|---|---|
| Appliqué automatiquement | Oui | Non (il faut utiliser -f) |
| Gestion du code source | Montages bind pour les mises à jour en direct | Images préconfigurées à partir du registre |
| Variables d'environnement | Valeurs axées sur les développeurs | Valeurs sécuritaires pour la production |
| Exploitation forestière | Verbeux (debug) | Concise (info ou error) |
| Gestion des secrets | Valeurs simples ou .env | Secrets Docker ou secrets gérés |
| Mise à l'échelle | Conteneur unique | Multiples répliques |
| Optimisation des performances | Non requis | Limites de ressources définies |
| Outils de débogage | Activé | Désactivé |
| Politique de redémarrage | Manuel ou aucun | |
L'utilisation de plusieurs fichiers Docker Compose offre un moyen clair de séparer les configurations spécifiques à l'environnement de la configuration de base. Le fichier de base docker-compose.yml définit la structure commune de l'application, tandis que docker-compose.override.yml l'ajuste pour le développement local. Lors du déploiement en production, un fichier de substitution explicite garantit une configuration prévisible et sécurisée.
Ce modèle permet aux équipes de maintenir un flux de travail cohérent. Les développeurs peuvent démarrer l'application localement en utilisant :
docker compose upet déployer en production en utilisant :
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dLes deux environnements partagent la même configuration de base tout en conservant des paramètres indépendants adaptés à leurs besoins spécifiques. Cette séparation améliore la maintenabilité, réduit les erreurs de configuration et maintient l'alignement entre les environnements locaux et de production.
Dépannage de votre environnement
Cette section fournit des étapes de dépannage pour les problèmes courants que vous pourriez rencontrer lors de l'exécution de votre application avec Docker Compose.
502 Mauvaise passerelle (Nginx affiche des réponses 502)
Symptômes :
- Le navigateur affiche 502 Mauvaise passerelle lors de l'accès à
http://localhost:8000. - Les journaux Nginx contiennent des lignes telles que
recv() failed (111: Connection refused)ouconnect() failed (111: Connection refused) while connecting to upstream.
Causes probables :
- PHP-FPM (le service
app) ne fonctionne pas ou n'écoute pas sur le socket/port attendu. - Nginx
fastcgi_passpointe vers le mauvais hôte/port. - Incohérence dans le nom du conteneur ou problèmes de réseau entre
nginxetapp. apps'est écrasée au démarrage (par exemple, en raison d'extensions manquantes ou d'erreurs de configuration).
Comment confirmer :
Inspecter les journaux Nginx :
docker compose logs nginx | tail -n 100Recherchez les messages
502ou les erreurs de connexion en amont.Vérifiez l'état et les journaux du conteneur
app:docker compose ps app docker compose logs app --tail=200Vérifiez que PHP-FPM écoute à l'intérieur du conteneur
app:docker compose exec app ss -ltnp | grep :9000 || docker compose exec app ss -lxp | grep php-fpmPrévu : soit un écouteur TCP sur le port
9000, soit un socket Unix utilisé parnginx(moins courant avec ce compose).Confirmez que
nginxpeut résoudre et atteindreappsur le réseau compose :docker compose exec nginx ping -c 2 app docker compose exec nginx wget -qO- --timeout=2 http://app:9000/ || trueSi
pingéchoue ou siwgetdépasse le délai, il y a un problème de réseau ou un décalage dans le nom du service.
Solutions courantes :
Si PHP-FPM ne fonctionne pas, inspectez les journaux de
apppour les erreurs PHP fatales ou les échecs de démarrage. Corrigez l'erreur sous-jacente (souvent une extension manquante ou un problème de permission) et redémarrez :docker compose restart app docker compose logs app --tail=100Si la configuration de Nginx utilise un upstream différent (par ex.,
fastcgi_pass 127.0.0.1:9000;), mettez à jourdocker-compose/nginx/travellist.confenfastcgi_pass app:9000;(pour correspondre au nom de votre service dans compose) et rechargez Nginx :# After editing config in host docker compose exec nginx nginx -s reload docker compose logs nginx --tail=50Si PHP-FPM écoute sur un socket Unix (par exemple,
/run/php/php7.4-fpm.sock) mais que Nginx attend du TCP ou vice versa, standardisez sur le TCPapp:9000pour les configurations Compose ou montez correctement le socket entre les conteneurs (recommandé : utiliser le TCP dans un Compose multi-conteneurs).
Extensions PHP manquantes (erreurs lors de l'exécution de Composer ou Artisan, ou échecs à l'exécution)
Symptômes :
- Les commandes Composer ou Laravel échouent avec des messages tels que
Classe "PDO" introuvable,ext-pdo manquanteouAppel à une fonction non définie json_encode. - Erreurs PHP dans les journaux de
appfaisant référence à des classes ou fonctions non définies.
Comment confirmer :
Inspectez la liste des modules PHP du conteneur
app:docker compose exec app php -m | sortRecherchez les noms des extensions dont vous avez besoin (pour les extensions typiques de Laravel :
pdo_mysql,mbstring,bcmath,openssl,tokenizer,xml,ctype,json,gd).Vérifiez le texte d'erreur de Composer qui indique généralement les extensions requises :
docker compose exec app composer install
Correctifs :
Ajoutez les extensions manquantes dans votre Dockerfile et reconstruisez l'image. Exemple (pour
pdo_mysqletgd) :RUN apt-get update && apt-get install -y libpng-dev libxml2-dev \ && docker-php-ext-install pdo_mysql mbstring xml gdEnsuite, reconstruisez et redémarrez :
docker compose build app docker compose up -d app docker compose logs app --tail=100Si une extension nécessite des bibliothèques système (par exemple
gda besoin delibpng-dev), ajoutez les lignes correspondantesapt-get installavantdocker-php-ext-install.Si vous avez besoin d'une extension PHP qui n'est pas intégrée, envisagez de l'installer via PECL et de l'activer dans
php.ini.
Échecs de connexion à la base de données (Laravel ne peut pas se connecter à MySQL)
Symptômes :
- Laravel affiche des erreurs de connexion à la base de données (
SQLSTATE[HY000] [2002] Connexion refuséeouAccès refusé pour l'utilisateur). - Les migrations échouent ou l'application affiche une page vide pour les pages basées sur les données.
Comment confirmer :
Vérifiez les journaux du conteneur de base de données pour détecter les erreurs d'initialisation :
docker compose logs db --tail=200Vérifiez que le conteneur de BD est en marche :
docker compose ps dbVérifiez que les identifiants et l'hôte sont cohérents entre
.envetdocker-compose.yml. Dans le.envde Laravel,DB_HOSTdoit être le nom du service dans le compose (db), et non127.0.0.1oulocalhost:DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=passwordTest depuis l'intérieur du conteneur
db:docker compose exec db mysql -u"${DB_USERNAME}" -p"${DB_PASSWORD}" -e "SHOW DATABASES;"Ou, testez depuis le conteneur
apppour vérifier la connectivité réseau :docker compose exec app sh -c 'which mysql >/dev/null 2>&1 || echo "no mysql client"; mysql -h db -u"${DB_USERNAME}" -p"${DB_PASSWORD}" -e "SELECT VERSION();"'
Causes courantes et solutions :
Hôte incorrect dans
.env: mettez à jourDB_HOST=db, recréez les conteneurs ou rechargez les variables d'environnement :docker compose down docker compose up -d docker compose exec app php artisan migrateLa base de données n'est pas prête au démarrage de l'application : utilisez un mécanisme de nouvelle tentative dans votre application ou ajoutez un contrôle de santé et commencez à passer des commandes. Vous pouvez également attendre manuellement :
docker compose exec db mysqladmin -u"${DB_USERNAME}" -p"${DB_PASSWORD}" ping # expected: mysqld is aliveÉchec de l'initialisation SQL : vérifiez les fichiers sous
./docker-compose/mysql, une erreur de syntaxe ou de permission peut interrompre l'initialisation de la base de données. Consultez les journaux de la base pour les erreurs d'importation.Privilèges/identifiants incorrects : confirmez que la base de données et l’utilisateur existent. Recréez la base de données ou exécutez du SQL pour accorder les privilèges.
Utilisation des ports au niveau hôte : si vous avez tenté
curl telnet://localhost:3306et que le servicedbn’expose pas de port sur l’hôte, cette connexion sera refusée par conception. Testez depuis l’intérieur des conteneurs ou exposez le port dansdocker-compose.yml(ports: - "3306:3306") pour le débogage local uniquement.
Problèmes de permissions et de système de fichiers (stockage, cache, fichiers journaux)
Symptômes :
- Laravel génère des exceptions liées à l’écriture du cache ou des journaux :
Le flux ou le fichier "/var/www/storage/logs/laravel.log" n’a pas pu être ouvert. - Les fichiers créés par les processus du conteneur appartiennent à
rootet ne peuvent pas être modifiés par votre utilisateur hôte.
Comment confirmer :
Vérifiez les permissions de fichier depuis l'hôte :
ls -l ls -l storage bootstrap/cache docker compose exec app id -u # user id inside containerVérifiez les journaux du conteneur pour détecter les erreurs d'autorisation.
Correctifs :
Assurez-vous que le Dockerfile définit l'utilisateur et l'UID correspondant à votre utilisateur hôte (votre Dockerfile crée déjà un utilisateur avec
ARG uid). Vérifiez que leuiddans les arguments de build dedocker-compose.ymlcorrespond à votre UID hôte (généralement1000).Corriger la propriété depuis l’hôte ou à l’intérieur du conteneur :
docker compose exec app chown -R sammy:sammy /var/www/storage /var/www/bootstrap/cacheou de l'hôte :
sudo chown -R $(id -u):$(id -g) storage bootstrap/cachePour le développement, les montages bind peuvent causer des conflits de permissions ; il est préférable d'exécuter des commandes dans le conteneur pour ajuster la propriété après avoir démarré les conteneurs.
Erreurs liées au compositeur ou au fournisseur
Symptômes :
- L'exécution de
composer installdansappéchoue ou l'absence du dossiervendorentraîne une erreur de classe introuvable. composersignale une surcharge de mémoire dans le conteneur.
Comment confirmer :
Exécutez composer à l'intérieur du conteneur
appet capturez la sortie :docker compose exec app composer install --no-interaction --prefer-dist
Corrections :
Si les limites de mémoire de
composersont atteintes, autorisez plus de mémoire ou définissez la variable d’environnement de composer :docker compose exec app php -d memory_limit=-1 /usr/bin/composer installAssurez-vous que l’exécutable Composer est présent (votre Dockerfile copie Composer). Sinon, reconstruisez l’image avec la couche Composer.
Si le dossier
vendorest manquant à cause d'une superposition de montage bind, assurez-vous que votre montage bind ne cache pas le dossiervendorcréé dans l'image. La meilleure pratique consiste à exécutercomposer installaprès le démarrage des conteneurs afin quevendorsoit créé dans le dossier monté, ou à ajoutervendorau conteneur via la construction de l'image pour la production.
L'application renvoie une page blanche ou des erreurs 500
Symptômes :
- Le navigateur affiche une réponse vide ou une erreur HTTP 500.
- Les journaux de Nginx montrent 200 mais la page est vide; les journaux de
appaffichent des exceptions fatales.
Comment confirmer :
Vérifier les journaux de l'application :
docker compose exec app tail -n 200 storage/logs/laravel.log docker compose logs app --tail=200Vérifiez l'environnement :
APP_DEBUG=truedans.envfera en sorte que Laravel affiche des erreurs détaillées en développement (ne pas activer en production).
Correctifs :
Corrigez l'exception sous-jacente indiquée dans
laravel.log.Assurez-vous que
.envexiste et queAPP_KEYest défini :docker compose exec app php artisan key:generateExécuter les migrations, vider le cache :
docker compose exec app php artisan migrate --force docker compose exec app php artisan config:cache docker compose exec app php artisan route:cache docker compose exec app php artisan view:cache
Échecs de construction de conteneurs (erreurs pendant docker compose build)
Symptômes :
- La commande
docker compose buildéchoue avec des erreurs liées à apt ou à l'étape de construction.
Comment confirmer :
Relancer la compilation avec les journaux :
docker compose build app
Correctifs :
Lisez la sortie de l’étape échouée. Problèmes typiques :
- Réseau/DNS dans l'environnement de build : réessayez ou assurez-vous que Docker peut accéder à Internet.
- Packages manquants ou source apt incorrecte : ajoutez
apt-get updateavant les installations et nettoyez les listes apt ensuite. - Autorisations sur les fichiers copiés dans l'image : assurez-vous que les chemins de
COPYsont corrects.
Exemple de fragment de Dockerfile pour des installations robustes :
RUN apt-get update && apt-get install -y --no-install-recommends \
libpng-dev libxml2-dev zip unzip \
&& docker-php-ext-install pdo_mysql mbstring xml gd \
&& apt-get clean && rm -rf /var/lib/apt/lists/*Problèmes de réseau ou de DNS entre les conteneurs
Symptômes :
- Un conteneur ne peut pas atteindre un autre par le nom du service (par exemple,
appne peut pas atteindredbavecdb:3306). pingpar nom de service échoue.
Comment confirmer :
docker compose exec app ping -c 3 db
docker compose exec app getent hosts db
docker network inspect travellistCorrectifs :
Confirmez que les services partagent le même réseau dans
docker-compose.yml(les deux devraient référencertravellist).Si vous avez changé les noms des services ou des réseaux, mettez à jour
DB_HOSTet les upstreams Nginx en conséquence.Recréer le réseau (cela détruit les conteneurs éphémères, donc faites attention) :
docker compose down docker network prune # optional and destructive docker compose up -d
Commandes de diagnostic utiles
Exécutez ceux-ci pour une inspection ciblée :
Afficher les conteneurs en cours d'exécution et les ports :
docker compose psJournaux en continu pour un service :
docker compose logs -f --tail=200 nginxExécuter un shell à l'intérieur d'un conteneur :
docker compose exec app sh docker compose exec db bashVérifier les variables d'environnement du conteneur :
docker compose exec app env | sort docker compose exec db env | grep MYSQLVérifier la liste des processus du conteneur :
docker compose exec app ps aux docker compose exec app ss -ltnpVérifier l'état de MySQL :
docker compose exec db mysqladmin -u"${DB_USERNAME}" -p"${DB_PASSWORD}" ping
Quand exposer les ports de l’hôte pour le débogage
Par défaut, le service db dans cette configuration n’est pas lié aux ports de l’hôte. N’exposez les ports que pour le débogage local. Pour exposer temporairement MySQL sur l’hôte, ajoutez dans docker-compose.yml sous db :
ports:
- "3306:3306"Puis redémarrez :
docker compose up -d dbAprès le débogage, supprimez le mappage ports pour éviter d'exposer la base de données au réseau.
FAQ
1. Ai-je besoin que Composer soit installé sur l'hôte ?
Non. Vous pouvez exécuter Composer entièrement à l'intérieur du conteneur de l'application, ce qui est l'approche recommandée pour ce flux de travail Compose. Le Dockerfile dans le tutoriel inclut Composer, donc exécutez des commandes comme docker compose exec app composer install ou docker compose run --rm app composer require vendor/package. Exécuter Composer dans le conteneur garantit que la bonne version de PHP et les extensions appropriées sont utilisées et évite de produire des fichiers vendor avec une propriété incorrecte sur l'hôte.
2. Puis-je exécuter des migrations Laravel depuis l'intérieur du conteneur ?
Oui. Exécutez les migrations depuis le conteneur de l'application afin qu'elles utilisent le même environnement d'exécution et le même réseau que votre application : docker compose exec app php artisan migrate. Pour des tâches ponctuelles ou CI, vous pouvez utiliser docker compose run --rm app php artisan migrate --force. Avant d'exécuter les migrations, assurez-vous que le conteneur de la base de données est sain et accepte les connexions, par exemple avec docker compose exec db mysqladmin -u$ {DB_USERNAME} -p$ {DB_PASSWORD} ping ou en réessayant jusqu'à ce qu'il réponde.
3. Comment puis-je installer des extensions PHP supplémentaires?
Ajoutez les packages système nécessaires et les commandes d'extension au Dockerfile, puis reconstruisez l'image. Par exemple, installez les dépendances et construisez les extensions courantes avec quelque chose comme :
RUN apt-get update && apt-get install -y libpng-dev libjpeg-dev \
&& docker-php-ext-configure gd --with-jpeg \
&& docker-php-ext-install pdo_mysql mbstring gdSi vous avez besoin d'une extension PECL, utilisez pecl install et docker-php-ext-enable. Après avoir modifié le Dockerfile, exécutez docker compose build app puis docker compose up -d app pour appliquer les changements.
4. Comment puis-je exposer le conteneur Nginx pour HTTPS ?
Ajoutez un bloc de serveur HTTPS à votre configuration Nginx, montez votre certificat et votre clé dans le conteneur, et publiez le port 443 dans docker-compose. Voici un exemple avec des modifications minimales dans docker-compose.yml :
services:
nginx:
ports:
- "8000:80"
- "443:443"
volumes:
- ./docker-compose/nginx:/etc/nginx/conf.d
- ./certs:/etc/nginx/certs:roAjoutez ensuite un bloc serveur SSL qui référence /etc/nginx/certs/fullchain.pem et /etc/nginx/certs/privkey.pem. Pour la production, utilisez un proxy inverse ou un gestionnaire de certificats comme Traefik ou un répartiteur de charge externe pour obtenir et renouveler les certificats de manière sécurisée, plutôt que de stocker les clés privées dans la pile de l'application.
5. Comment reconstruire Laravel après des modifications du code ?
Cela dépend de ce qui a changé. Si vous utilisez des montages bind pour le répertoire du projet, les changements dans PHP, les modèles, les routes et les contrôleurs sont reflétés immédiatement; exécutez les commandes de vidage du cache Laravel si nécessaire, par exemple :
docker compose exec app php artisan config:clear
docker compose exec app php artisan route:clear
docker compose exec app php artisan view:clearSi vous avez modifié les dépendances de Composer ou le Dockerfile (nouvelles extensions ou paquets système), réinstallez ou reconstruisez : docker compose exec app composer install pour les changements de dépendances, et docker compose build app && docker compose up -d pour les modifications du Dockerfile. Redémarrez le service affecté lorsque vous changez la configuration de PHP-FPM ou Nginx : docker compose restart app ou docker compose restart nginx.
Conclusion
Dans ce guide, nous avons mis en place un environnement Docker avec trois conteneurs en utilisant Docker Compose pour définir notre infrastructure dans un fichier YAML.
À partir de ce moment, vous pouvez travailler sur votre application Laravel sans avoir besoin d’installer et de configurer un serveur web local pour le développement et les tests. De plus, vous travaillerez avec un environnement jetable qui peut être facilement reproduit et distribué, ce qui peut être utile lors du développement de votre application et également lors de la transition vers un environnement de production.
Pour plus de tutoriels Laravel, consultez les articles suivants :
- Hébergez votre application Laravel sur Linux-Console.net
- Comment installer et configurer Laravel avec Nginx sur Ubuntu (pile LEMP)
- Comment créer des ressources API Eloquent Laravel pour convertir des modèles en JSON
- Comment lancer une nouvelle application Laravel avec Docker Compose
Merci de apprendre avec la communauté Linux-Console.net.

