Cum să instalezi și să configurezi Laravel cu Docker Compose pe Ubuntu 22.04
Introducere
A containera o aplicație se referă la procesul de adaptare a unei aplicații și a componentelor sale astfel încât să poată fi rulată în medii ușoare cunoscute sub numele de containere. Astfel de medii sunt izolate și de unică folosință și pot fi folosite pentru dezvoltarea, testarea și implementarea aplicațiilor în producție.
În acest ghid, vom folosi Docker Compose pentru a containeriza o aplicație Laravel pentru dezvoltare. Când veți termina, veți avea o aplicație demo Laravel care rulează pe trei containere de servicii separate:
- Un serviciu
appcare rulează PHP7.4-FPM; - Un serviciu
dbcare rulează MySQL 8.0; - Un serviciu
nginxcare utilizează serviciulapppentru a interpreta codul PHP înainte de a livra aplicația Laravel utilizatorului final.
Pentru a permite un proces de dezvoltare mai fluid și a facilita depanarea aplicației, vom menține fișierele aplicației sincronizate folosind volume partajate. De asemenea, vom vedea cum să folosim comenzile docker compose exec pentru a rula Composer și Artisan pe containerul app.
Deplasați aplicațiile frontend din GitHub folosind Platforma de Aplicații Linux-Console.net. Lăsați Linux-Console.net să se ocupe de scalarea aplicației dumneavoastră.
Aspecte esențiale:
- Containerizarea face dezvoltarea previzibilă: Rularea Laravel în Docker asigură medii consistente pe toate calculatoarele, eliminând problemele de tipul „funcționează pe calculatorul meu” și facilitând colaborarea.
- Separarea serviciilor îmbunătățește mentenabilitatea: Împărțirea PHP, MySQL și Nginx în containere separate ajută la izolarea problemelor, simplifică actualizările și reflectă configurațiile reale de producție.
- Variabilele de mediu sunt esențiale pentru configurarea flexibilă: Utilizarea unui fișier
.envpermite dezvoltatorilor să schimbe datele de autentificare ale bazei de date și alte setări fără a modifica codul aplicației. - Imaginile Docker personalizate îmbunătățesc controlul și securitatea: Crearea propriei imagini PHP asigură că instalați doar ceea ce are nevoie proiectul dvs., menținând mediul ușor și sigur.
- Permisiunile fișierelor trebuie să corespundă utilizatorilor containerului: Setarea proprietății și a permisiunilor corecte pentru directoarele scriibile ale Laravel previne erorile la rulare și susține un dezvoltare locală fără probleme.
- Folosirea fișierelor de suprascriere suportă mai multe medii:
docker-compose.override.ymlpermite ajustări locale—cum ar fi reîncărcarea live—fără a modifica configurațiile de producție. Aceasta menține dezvoltarea și implementarea clar separate. - depanarea începe cu înțelegerea comportamentului containerului: Cunoașterea modului de a inspecta jurnalele, de a verifica serviciile în funcțiune și de a testa conectivitatea este esențială pentru rezolvarea rapidă a majorității problemelor în mediile containerizate.
- O configurație bazată pe Docker se scalează odată cu fluxul tău de lucru: Odată construită, aceeași configurație poate alimenta mediile locale, de staging sau de producție, creând o bază stabilă și reutilizabilă pentru viitoarele proiecte Laravel.
Cerințe prealabile
- Acces la o mașină locală Ubuntu sau un server de dezvoltare ca utilizator non-root cu privilegii sudo. Dacă folosești un server de la distanță, este recomandat să ai un firewall activ instalat. Pentru a configura aceste lucruri, te rugăm să consulți Ghidul nostru de Configurare Inițială a Serverului pentru Ubuntu.
- Docker instalat pe serverul dvs., urmând Pașii 1 și 2 din Cum să instalați și să utilizați Docker pe Ubuntu.
- Docker Compose instalat pe serverul dvs., urmând Pasul 1 din Cum să instalați și să utilizați Docker Compose pe Ubuntu.
Pasul 1 — Obținerea aplicației demo
Pentru a începe, vom prelua aplicația demo Laravel din depozitul său Github. Ne interesează branch-ul tutorial-01, care conține aplicația de bază Laravel pe care am creat-o în ghidul Cum să instalezi și să configurezi Laravel cu Nginx pe Ubuntu 22.04 (LEMP).
Pentru a obține codul aplicației care este compatibil cu acest tutorial, descărcați versiunea tutorial-1.0.1 în directorul dvs. de acasă cu:
cd ~
curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zipVom avea nevoie de comanda unzip pentru a despacheta codul aplicației. În cazul în care nu ați instalat acest pachet anterior, faceți-o acum cu:
sudo apt update
sudo apt install unzipAcum, dezarhivați conținutul aplicației și redenumiți directorul extras pentru un acces mai ușor:
unzip travellist.zip
mv travellist-laravel-demo-tutorial-1.0.1 travellist-demoNavigați către directorul travellist-demo:
cd travellist-demoÎn pasul următor, vom crea un fișier de configurație .env pentru a configura aplicația.
Pasul 2 — Configurarea fișierului .env al aplicației
Fișierele de configurare Laravel se află într-un director numit config, în interiorul directorului rădăcină al aplicației. În plus, un fișier .env este folosit pentru a configura setările dependente de mediu, cum ar fi acreditările și orice informație care poate varia între implementări. Acest fișier nu este inclus în controlul versiunilor.
Atenție: Fișierul de configurare al mediului conține informații sensibile despre serverul dumneavoastră, inclusiv datele de autentificare la baza de date și cheile de securitate. Din acest motiv, nu ar trebui să partajați niciodată acest fișier public.
Valorile conținute în fișierul .env vor avea prioritate față de valorile setate în fișierele de configurare obișnuite aflate în directorul config. Fiecare instalare pe un mediu nou necesită un fișier de mediu personalizat pentru a defini aspecte precum setările de conectare la baza de date, opțiunile de depanare, URL-ul aplicației, printre alte elemente care pot varia în funcție de mediul în care rulează aplicația.
Acum vom crea un nou fișier .env pentru a personaliza opțiunile de configurare pentru mediul de dezvoltare pe care îl configurăm. Laravel vine cu un fișier exemplu .env pe care îl putem copia pentru a ne crea propriul fișier:
cp .env.example .envDeschide acest fișier folosind nano sau editorul de text preferat:
nano .envFișierul actual .env din aplicația demo travellist conține setări pentru a folosi o bază de date MySQL locală, cu 127.0.0.1 ca gazdă a bazei de date. Trebuie să actualizăm variabila DB_HOST astfel încât să indice către serviciul de baze de date pe care îl vom crea în mediul nostru Docker. În acest ghid, vom numi serviciul nostru de baze de date db. Mergeți mai departe și înlocuiți valoarea listată a DB_HOST cu numele serviciului bazei de date:
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
...Simțiți-vă liber să schimbați și numele bazei de date, numele de utilizator și parola, dacă doriți. Aceste variabile vor fi folosite într-un pas ulterior, când vom configura fișierul docker-compose.yml pentru a configura serviciile noastre.
Salvează fișierul când ai terminat de editat. Dacă ai folosit nano, poți face asta apăsând Ctrl+x, apoi Y și Enter pentru a confirma.
Pasul 3 – Configurarea Dockerfile-ului aplicației
Deși atât serviciile noastre MySQL, cât și Nginx vor fi bazate pe imagini implicite obținute de pe Docker Hub, avem totuși nevoie să construim o imagine personalizată pentru containerul aplicației. Vom crea un nou Dockerfile pentru aceasta.
Imaginea noastră travellist va fi bazată pe imaginea oficială PHP php:7.4-fpm de pe Docker Hub. Peste acest mediu de bază PHP-FPM, vom instala câteva module PHP suplimentare și instrumentul de gestionare a dependențelor Composer.
De asemenea, vom crea un nou utilizator de sistem; acest lucru este necesar pentru a executa comenzile artisan și composer în timp ce dezvoltăm aplicația. Setarea uid asigură că utilizatorul din interiorul containerului are același uid ca utilizatorul tău de pe sistemul gazdă, unde rulezi Docker. Astfel, orice fișiere create de aceste comenzi sunt redate pe gazdă cu permisiunile corecte. Aceasta înseamnă, de asemenea, că vei putea folosi editorul de cod preferat pe mașina gazdă pentru a dezvolta aplicația care rulează în interiorul containerelor.
Creează un nou Dockerfile cu:
nano DockerfileCopiați următorul conținut în Dockerfile-ul dvs.:
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
Nu uita să salvezi fișierul când termini.
Dockerfile-ul nostru începe prin definirea imaginii de bază pe care o folosim: php:7.4-fpm.
După instalarea pachetelor de sistem și a extensiilor PHP, instalăm Composer copiind executabilul composer din cea mai recentă imagine oficială în propria noastră imagine a aplicației.
Un nou utilizator de sistem este apoi creat și configurat folosind argumentele user și uid care au fost declarate la începutul Dockerfile-ului. Aceste valori vor fi injectate de Docker Compose în timpul construirii.
În cele din urmă, setăm directorul de lucru implicit ca /var/www și schimbăm utilizatorul către cel nou creat. Acest lucru va asigura că te conectezi ca utilizator obișnuit și că ești în directorul corect atunci când rulezi comenzile composer și artisan în containerul aplicației.
Pasul 4 — Configurarea fișierelor de configurare Nginx și a fișierelor de depanare a bazei de date
Atunci când creezi medii de dezvoltare cu Docker Compose, este adesea necesar să partajezi fișiere de configurare sau de inițializare cu containerele de servicii, pentru a configura sau a porni acele servicii. Această practică facilitează modificarea fișierelor de configurare pentru a ajusta fin mediul tău în timp ce dezvolți aplicația.
Acum vom configura un folder cu fișiere care vor fi folosite pentru a configura și inițializa containerele noastre de servicii.
Pentru a configura Nginx, vom împărtăși un fișier travellist.conf care va configura modul în care este servită aplicația. Creați folderul docker-compose/nginx cu:
mkdir -p docker-compose/nginxDeschide un fișier nou numit travellist.conf în acel director:
nano docker-compose/nginx/travellist.confCopiați următoarea configurație Nginx în acel fișier:
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;
}
}Acest fișier va configura Nginx să asculte pe portul 80 și să folosească index.php ca pagină implicită de index. Va seta rădăcina documentului la /var/www/public și apoi va configura Nginx să folosească serviciul app pe portul 9000 pentru a procesa fișierele *.php.
Salvați și închideți fișierul când ați terminat de editat.
Pentru a configura baza de date MySQL, vom partaja un dump al bazei de date care va fi importat atunci când containerul este inițializat. Aceasta este o funcție oferită de imaginea MySQL 8.0 pe care o vom folosi pe acel container.
Creează un folder nou pentru fișierele tale de inițializare MySQL în interiorul folderului docker-compose:
mkdir docker-compose/mysqlDeschideți un fișier nou .sql:
nano docker-compose/mysql/init_db.sqlUrmătorul dump MySQL se bazează pe baza de date pe care am configurat-o în ghidul nostru Laravel pe LEMP. Va crea un tabel nou numit places. Apoi, va popula tabelul cu un set de locuri de exemplu.
Adaugă următorul cod în fișier:
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);Tabelul places conține trei câmpuri: id, name și visited. Câmpul visited este un indicator folosit pentru a identifica locurile care încă sunt de vizitat. Te poți simți liber să schimbi locurile din exemplu sau să adaugi altele noi. Salvează și închide fișierul când ai terminat.
Am terminat de configurat Dockerfile-ul aplicației și fișierele de configurare ale serviciului. Următorul pas este să configurăm Docker Compose pentru a folosi aceste fișiere la crearea serviciilor noastre.
Pasul 5 — Crearea unui mediu cu mai multe containere folosind Docker Compose
Docker Compose îți permite să creezi medii cu mai multe containere pentru aplicații care rulează pe Docker. Folosește definiții de servicii pentru a construi medii complet personalizabile cu multiple containere care pot partaja rețele și volume de date. Acest lucru permite o integrare fără probleme între componentele aplicației.
Pentru a configura definițiile serviciilor noastre, vom crea un fișier nou numit docker-compose.yml. De obicei, acest fișier se află în rădăcina folderului aplicației și definește mediul containerizat, inclusiv imaginile de bază pe care le veți folosi pentru a construi containerele și modul în care serviciile voastre vor interacționa.
Vom defini trei servicii diferite în fișierul nostru docker-compose.yml: app, db și nginx.
Serviciul app va construi o imagine numită travellist, bazată pe Dockerfile-ul pe care l-am creat anterior. Containerul definit de acest serviciu va rula un server php-fpm pentru a interpreta codul PHP și a trimite rezultatele înapoi către serviciul nginx, care va rula într-un container separat. Serviciul mysql definește un container care rulează un server MySQL 8.0. Serviciile noastre vor partaja o rețea bridge numită travellist.
Fișierele aplicației vor fi sincronizate atât pe serviciile app, cât și pe nginx prin bind mounts. Bind mounts sunt utile în mediile de dezvoltare deoarece permit o sincronizare bidirecțională performantă între mașina gazdă și containere.
Creează un nou fișier docker-compose.yml în directorul rădăcină al aplicației:
nano docker-compose.ymlUn fișier tipic docker-compose.yml începe cu o definiție a versiunii, urmată de un nod services, sub care sunt definite toate serviciile. Rețelele partajate sunt de obicei definite în partea de jos a acelui fișier.
Pentru a începe, copiază acest cod standard în fișierul tău docker-compose.yml:
version: "3.9"
services:
networks:
travellist:
driver: bridgeAcum vom edita nodul services pentru a include serviciile app, db și nginx.
Serviciul app
Serviciul app va configura un container numit travellist-app. Acesta construiește o nouă imagine Docker bazată pe un Dockerfile aflat în aceeași cale cu fișierul docker-compose.yml. Noua imagine va fi salvată local sub numele travellist.
Chiar dacă rădăcina documentului servită ca aplicație se află în containerul nginx, avem nevoie ca fișierele aplicației să fie undeva și în containerul app, astfel încât să putem executa sarcini din linia de comandă cu uneltele Laravel Artisan.
Copiați următoarea definiție de serviciu sub nodul services, în interiorul fișierului 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:
- travellistAceste setări fac următoarele:
build: Această configurație indică Docker Compose să construiască o imagine locală pentru serviciulapp, folosind calea specificată (context) și Dockerfile-ul pentru instrucțiuni. Argumenteleuserșiuidsunt injectate în Dockerfile pentru a personaliza comenzile de creare a utilizatorului la momentul construirii.image: Numele care va fi utilizat pentru imaginea care este construită.container_name: Setează numele containerului pentru acest serviciu.restart: Reporniți întotdeauna, cu excepția cazului în care serviciul este oprit.working_dir: Setează directorul implicit pentru acest serviciu ca/var/www.volumes: Creează un volum partajat care va sincroniza conținutul din directorul curent către/var/wwwdin interiorul containerului. Observați că acesta nu este rădăcina documentelor dvs., deoarece aceasta va fi în containerulnginx.rețele: Configurează acest serviciu pentru a utiliza o rețea numitătravellist.
Serviciul db
Serviciul db folosește o imagine MySQL 8.0 pre-construită de pe Docker Hub. Deoarece Docker Compose încarcă automat fișierele de variabile .env aflate în același director cu fișierul docker-compose.yml, putem prelua setările bazei noastre de date din fișierul Laravel .env pe care l-am creat într-un pas anterior.
Include următoarea definiție de serviciu în nodul tău services, imediat după serviciul 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:
- travellistAceste setări fac următoarele:
image: Define imaginea Docker care trebuie folosită pentru acest container. În acest caz, folosim o imagine MySQL 8.0 de pe Docker Hub.container_name: Setează numele containerului pentru acest serviciu:travellist-db.restart: Repornește întotdeauna acest serviciu, cu excepția cazului în care este oprit în mod explicit.environment: Define variabilele de mediu în noul container. Folosim valori obținute din fișierul Laravel.envpentru a configura serviciul nostru MySQL, care va crea automat o bază de date și un utilizator nou pe baza variabilelor de mediu furnizate.volumes: Creează un volum pentru a partaja un dump de bază de date.sqlcare va fi folosit pentru a inițializa baza de date a aplicației. Imaginea MySQL va importa automat fișierele.sqlplasate în directorul/docker-entrypoint-initdb.ddin interiorul containerului.rețele: Configurează acest serviciu pentru a utiliza o rețea numitătravellist.
Serviciul nginx
Serviciul nginx folosește o imagine Nginx pre-construită pe baza Alpine, o distribuție Linux ușoară. Creează un container numit travellist-nginx și utilizează definiția ports pentru a crea o redirecționare de la portul 8000 de pe sistemul gazdă către portul 80 din interiorul containerului.
Include următoarea definiție de serviciu în nodul tău services, imediat după serviciul 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:
- travellistAceste setări fac următoarele:
image: Define imaginea Docker care ar trebui folosită pentru acest container. În acest caz, folosim imaginea Alpine Nginx 1.17.container_name: Setează numele containerului pentru acest serviciu: travellist-nginx.restart: Reporniți întotdeauna acest serviciu, cu excepția cazului în care este oprit în mod explicit.ports: Configurează o redirecționare a portului care va permite accesul extern prin portul8000către serverul web care rulează pe portul80din interiorul containerului.volumes: Creează două volume partajate. Primul va sincroniza conținutul din directorul curent cu/var/wwwdin interiorul containerului. În acest mod, atunci când faci modificări locale în fișierele aplicației, acestea vor fi reflectate rapid în aplicația servită de Nginx din interiorul containerului. Al doilea volum se va asigura că fișierul nostru de configurare Nginx, aflat ladocker-compose/nginx/travellist.conf, este copiat în folderul de configurare Nginx al containerului.rețele: Configurează acest serviciu să utilizeze o rețea numitătravellist.
Fișier docker-compose.yml finalizat
Așa arată fișierul nostru final docker-compose.yml:
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: bridgeAsigură-te că salvezi fișierul când termini.
Pasul 6 — Rularea aplicației cu Docker Compose
Acum vom folosi comenzile docker compose pentru a construi imaginea aplicației și a rula serviciile pe care le-am specificat în configurația noastră.
Construiește imaginea app cu următoarea comandă:
docker compose build appAceastă comandă ar putea dura câteva minute pentru a se finaliza. Vei vedea un rezultat asemănător cu acesta:
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:latestCând compilarea este terminată, poți rula mediul în modul background cu:
docker compose up -dCreating travellist-db ... done
Creating travellist-app ... done
Creating travellist-nginx ... doneAcest lucru va rula containerele tale în fundal. Pentru a afișa informații despre starea serviciilor tale active, rulează:
docker compose psVei vedea un rezultat ca acesta:
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/tcpMediul tău este acum activ și funcțional.
Acum puteți verifica dacă fiecare serviciu containerizat răspunde corect folosind comenzi simple curl.
Pentru a testa serviciul web Nginx:
curl -I http://localhost:8000Rezultat așteptat:
HTTP/1.1 200 OK Server: nginx/1.17.10 Content-Type: text/html; charset=UTF-8Acest lucru confirmă că containerul Nginx rulează și oferă răspunsuri din aplicația ta Laravel.
Pentru a testa PHP-FPM prin Nginx:
curl -s http://localhost:8000 | grep "Berlin"Dacă aplicația rulează corect, această comandă returnează HTML-ul paginii de bun venit care include cuvântul Berlin.
Trebuie să executăm încă câteva comenzi pentru a finaliza configurarea aplicației. Poți folosi comanda docker compose exec pentru a executa comenzi în containerele serviciilor, cum ar fi ls -l pentru a afișa informații detaliate despre fișierele din directorul aplicației:
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.jsAcum vom rula composer install pentru a instala dependențele aplicației:
docker compose exec app rm -rf vendor composer.lock
docker compose exec app composer installVei vedea un rezultat ca acesta:
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.Ultimul lucru pe care trebuie să-l facem înainte de a testa aplicația este să generăm o cheie unică pentru aplicație folosind instrumentul de linie de comandă artisan din Laravel. Această cheie este folosită pentru a cripta sesiunile utilizatorilor și alte date sensibile:
docker compose exec app php artisan key:generateApplication key set successfully.Acum mergi la browserul tău și accesează numele de domeniu sau adresa IP a serverului tău pe portul 8000:
http://server_domain_or_IP:8000Notă: Dacă rulați această demonstrație pe calculatorul dumneavoastră, folosiți http://localhost:8000 pentru a accesa aplicația din browserul dumneavoastră.
Vei vedea o pagină ca aceasta:
De asemenea, poți testa aplicația Laravel din interiorul containerului aplicației fără a folosi un browser:
docker compose exec app curl http://nginxDacă totul este configurat corect, ar trebui să vedeți rezultatul HTML al paginii de bun venit implicite din 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>Poți folosi comanda logs pentru a verifica jurnalele generate de serviciile tale:
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"De asemenea, poți folosi următoarea comandă curl pentru a declanșa înregistrări în jurnal:
curl http://localhost:8000Apoi rulează din nou:
docker compose logs nginxAr trebui să vedeți acum o intrare corespunzătoare în jurnalul de acces pentru cererea dvs.
Dacă doriți să puneți în pauză mediul Docker Compose păstrând starea tuturor serviciilor sale, rulați:
docker compose pausePausing travellist-db ... done
Pausing travellist-nginx ... done
Pausing travellist-app ... doneApoi vă puteți relua serviciile cu:
docker compose unpauseUnpausing travellist-app ... done
Unpausing travellist-nginx ... done
Unpausing travellist-db ... donePentru a închide mediul dvs. Docker Compose și a elimina toate containerele, rețelele și volumele acestuia, rulați:
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_travellistPentru o prezentare generală a tuturor comenzilor Docker Compose, vă rugăm să consultați referința comenzilor Docker Compose.
Fixarea permisiunilor fișierelor și directoarelor în Laravel
Când rulezi Laravel în containere Docker, una dintre cele mai frecvente probleme cu care se confruntă dezvoltatorii este legată de permisiunile fișierelor și directoarelor. Laravel necesită ca anumite directoare să fie scriibile de procesul PHP-FPM din interiorul containerului app. Dacă aceste directoare nu sunt scriibile, aplicația poate eșua în a înregistra erori, a salva fișierele de configurare în cache sau a stoca corect datele de sesiune.
S-ar putea să întâlniți mesaje precum:
The stream or file "/var/www/storage/logs/laravel.log" could not be opened in append mode: failed to open stream: Permission deniedsau
file_put_contents(/var/www/bootstrap/cache/config.php): Failed to open stream: Permission deniedAceste erori indică faptul că utilizatorul care rulează PHP în container nu are permisiunea de a scrie în directoarele necesare.
Următorii pași descriu cum să diagnosticați și să rezolvați aceste probleme atât în mediile locale, cât și în cele de producție.
Ajustați permisiunile directorului inscripționabil
Laravel necesită ca două directoare să fie scrisibile de către utilizatorul serverului web:
/var/www/storage/var/www/bootstrap/cache
Dacă vedeți erori de permisiune, le puteți remedia ajustând proprietatea și permisiunile din interiorul containerului:
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/cacheDacă Dockerfile-ul tău folosește un alt nume de utilizator (definit prin argumentul de construire user), înlocuiește sammy cu acel nume de utilizator.
Puteți verifica proprietatea folosind comanda următoare:
docker compose exec app ls -ld /var/www/storage /var/www/bootstrap/cacheRezultatul ar trebui să arate că utilizatorul și grupul corespund procesului PHP-FPM din interiorul containerului.
Dacă vrei să ajustezi permisiunile de pe mașina gazdă, rulează:
sudo chown -R $(id -u):$(id -g) storage bootstrap/cache
sudo chmod -R 775 storage bootstrap/cacheAcest lucru asigură că ambele directoare Laravel sunt scriitoare atât de către container, cât și de către utilizatorul dvs. gazdă.
Setați drepturile de proprietate asupra directorului în timpul construirii imaginii
Pentru a preveni reapariția problemelor de permisiuni după fiecare reconstruire, puteți seta proprietatea directorului în timpul procesului de construire a imaginii Docker. Deschideți Dockerfile și adăugați următoarea linie aproape de sfârșit, înainte de a trece la utilizatorul non-root:
RUN chown -R $user:www-data /var/wwwAceastă comandă asigură că toate fișierele și directoarele din /var/www sunt deținute de utilizatorul pe care l-ați definit în Dockerfile-ul dumneavoastră.
Pentru o abordare mai țintită și sigură, poți ajusta doar directoarele în care Laravel trebuie să scrie:
RUN chown -R $user:www-data /var/www/storage /var/www/bootstrap/cacheDupă ce faceți această modificare, reconstruiți imaginea și reporniți containerele:
docker compose build app
docker compose up -dData viitoare când containerul va porni, va avea deja permisiunile corecte.
Verifică consistența ID-ului utilizatorului între gazdă și container
Atunci când folosiți bind mounts, Docker partajează fișiere între gazdă și container. Dacă UID-ul numeric al utilizatorului de pe gazdă diferă de UID-ul definit în container, pot apărea conflicte de proprietate a fișierelor. Acest lucru este obișnuit pe sistemele în care ID-urile utilizatorilor variază între mașini.
Pentru a verifica valorile UID, rulează:
id -u $(whoami)
docker compose exec app id -uDacă aceste două numere nu corespund, actualizează fișierul tău docker-compose.yml pentru a transmite UID-ul tău real procesului de construire:
build:
args:
user: sammy
uid: 1000Apoi reconstruiește imaginea:
docker compose build app
docker compose up -dAceasta asigură că utilizatorul containerului se potrivește cu utilizatorul gazdă, prevenind neconcordanțele de permisiuni pentru fișierele montate.
Remediați permisiunile directorului cache Composer
Composer stochează dependențele descărcate și fișierele cache în directorul de acasă al utilizatorului din interiorul containerului (/home/sammy/.composer). Dacă acest director nu este scriibil, este posibil să vedeți avertismente de genul:
Cannot create cache directory /home/sammy/.composer/cachePoți remedia acest lucru creând directorul de cache și atribuindu-i proprietarul corect:
docker compose exec app mkdir -p /home/sammy/.composer/cache
docker compose exec app chown -R sammy:sammy /home/sammy/.composerAcest lucru asigură că Composer poate stoca dependențele și fișierele cache fără erori de permisiune, ceea ce accelerează și rulările viitoare ale comenzii composer install.
Practici recomandate pentru mediile de producție
În producție, gestionarea permisiunilor ar trebui realizată în timpul construirii imaginii, și nu la rulare. Acest lucru îmbunătățește consistența și securitatea.
Urmărește aceste practici pentru o configurație pregătită pentru producție:
Evită montările legate pentru codul aplicației: În schimb, copiază fișierele aplicației în imagine în timpul construirii. Montările legate ar trebui să fie rezervate pentru dezvoltare.
Setați permisiunile în timpul construirii: Adăugați comenzile
RUN chownșichmodîn Dockerfile-ul dvs. pentru a asigura proprietatea și drepturile de acces corecte înainte de implementare.Folosește utilizatorul cu cele mai mici privilegii: Asigură-te că procesul PHP rulează sub un utilizator non-root (configurația actuală cu
$userdeja face acest lucru).Restricționați permisiunile pentru directoarele nedeschisibile la scriere: Majoritatea fișierelor aplicației ar trebui să fie doar pentru citire. Puteți face acest lucru prin:
chmod -R 755 /var/www chmod -R 775 /var/www/storage /var/www/bootstrap/cacheAceastă configurare permite Laravel să scrie doar acolo unde este necesar, protejând în același timp celelalte fișiere ale aplicației de modificare.
Urmând acești pași, containerele tale Laravel vor avea permisiuni de fișiere stabile și previzibile atât în mediile locale, cât și în cele de producție. Acest lucru reduce erorile recurente și asigură că Laravel poate înregistra date, stoca fișiere în cache și scrie sesiuni în mod fiabil.
Înțelegerea fișierului docker-compose.override.yml pentru mediile locale și de producție
Docker Compose îți permite să definești aplicații cu mai multe containere folosind un singur fișier de configurare. În majoritatea cazurilor, această configurație este stocată într-un fișier numit docker-compose.yml. Cu toate acestea, gestionarea mai multor medii, cum ar fi dezvoltarea locală și producția, necesită adesea ajustări specifice mediului. Aici devine util fișierul docker-compose.override.yml.
În mod implicit, Docker Compose caută automat un fișier numit docker-compose.override.yml în același director cu fișierul de bază Compose. Când este găsit, acesta combină configurațiile din ambele fișiere atunci când rulezi orice comandă docker compose. Această abordare permite dezvoltatorilor să mențină o configurație de bază curată și reutilizabilă, în timp ce personalizează aspecte specifice ale setup-ului pentru utilizare locală sau în producție.
Rolul fișierului docker-compose.override.yml
Fișierul docker-compose.override.yml este o extensie a configurației de bază Compose. Acesta modifică sau adaugă proprietăți care se aplică doar unui anumit mediu, fără a necesita modificări ale fișierului principal docker-compose.yml. Fișierul de override este deosebit de util în fluxurile de lucru de dezvoltare locală, unde dezvoltatorii trebuie adesea să monteze codul sursă, să activeze unelte de depanare sau să modifice variabile de mediu pentru testare.
Când execuți comanda docker compose up, Docker combină automat conținutul fișierelor docker-compose.yml și docker-compose.override.yml. Dacă un serviciu, volum sau configurație este definit în ambele fișiere, valorile din fișierul de suprascriere au prioritate.
Pentru a folosi un fișier de suprascriere diferit, de exemplu, unul destinat producției, poți specifica fișierul manual folosind flag-ul -f:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dAceastă abordare îți permite să menții configurații separate pentru diferite medii, folosind în același timp o structură de comandă unică și coerentă.
Structurarea pentru dezvoltarea locală
Mediile de dezvoltare locale necesită de obicei modificări frecvente, reîncărcare live a codului și înregistrare detaliată. Fișierul docker-compose.override.yml face posibilă introducerea acestor funcționalități fără a afecta alte medii.
Un fișier tipic de suprascriere locală poate include:
- Montări legate pentru actualizări live de cod
- Directive de construire locală în loc de utilizarea imaginilor preconstruite
- Variabile de mediu specifice dezvoltării
- Servicii de depanare și testare
De exemplu:
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=postgresÎn acest exemplu:
- Serviciul
appse construiește direct dintr-un Dockerfile local (Dockerfile.dev), ceea ce facilitează testarea modificărilor fără a reconstrui imaginile printr-un registru. - Codul sursă este montat folosind montări bind, permițând containerului să reflecte modificările fișierelor locale în timp real.
- Variabilele de mediu precum
LOG_LEVEL=debugsunt setate pentru a oferi ieșiri mai detaliate în timpul dezvoltării. - Baza de date folosește acreditive simple care sunt potrivite pentru testarea locală, dar nu ar trebui utilizate în producție.
Această configurație oferă un mediu de dezvoltare mai rapid și mai flexibil, păstrând în același timp configurația de bază neschimbată.
Pregătirea pentru producție
Mediile de producție necesită stabilitate, reproductibilitate și securitate. Containerele ar trebui să ruleze din imagini preconstruite, mai degrabă decât să fie construite local, iar informațiile sensibile trebuie gestionate în mod sigur. Spre deosebire de fișierul de suprascriere aplicat automat folosit pentru dezvoltarea locală, suprascrierile pentru producție trebuie specificate în mod explicit.
Un fișier de suprascriere pentru producție (docker-compose.prod.yml) este de obicei conceput pentru a înlocui pașii de construire locali cu referințe la imagini, pentru a folosi volume denumite în locul montărilor directe și pentru a defini proprietăți legate de implementare, cum ar fi limitele de resurse și scalarea.
Exemplu:
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:În această configurație:
Serviciul
appface referire la o imagine preconstruită (myapp:1.2.3) stocată într-un registru, în loc să fie construită local.Montările legate sunt înlocuite cu volume denumite pentru a asigura stocarea datelor într-un mod constant și izolat.
Datele de autentificare sensibile sunt stocate în siguranță folosind secrete Docker.
Secțiunea
deploydefinește comportamentul de scalare și limitele de resurse pentru o stabilitate mai bună sub sarcină.Configurația trebuie aplicată în mod explicit în timpul implementării:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Această structură asigură că implementările de producție sunt consistente, controlate și lipsite de artefacte provenite din dezvoltarea locală.
Compararea suprascrierilor locale și de producție
| Aspectul configurației | Local (docker-compose.override.yml) | Producție (docker-compose.prod.yml) |
|---|---|---|
| Aplicat automat | Da | Nu (trebuie să folosiți -f) |
| Gestionarea codului sursă | Montări legate pentru actualizări în timp real | Imagini preconfigurate din registru |
| Variabile de mediu | Valori orientate către dezvoltatori | Valori sigure pentru producție |
| Exploatare forestieră | Verbose (debug) | Concis (info sau eroare) |
| Gestionarea secretelor | Valori simple sau .env | Secrete Docker sau secrete gestionate |
| Scalare | Recipient individual | Mai multe replici |
| Optimizarea performanței | Nu este necesar | Limite de resurse definite |
| Unelte de depanare | Activat | Dezactivat |
| Politica de repornire | Manual sau deloc | |
Utilizarea mai multor fișiere Docker Compose oferă o modalitate clară de a separa configurațiile specifice mediului de setările de bază. Fișierul de bază docker-compose.yml definește structura comună a aplicației, în timp ce docker-compose.override.yml o ajustează pentru dezvoltarea locală. Atunci când se face implementarea în producție, un fișier de override explicit asigură o configurare predictibilă și sigură.
Acest model permite echipelor să mențină un flux de lucru constant. Dezvoltatorii pot porni aplicația local folosind:
docker compose upși să implementați în producție utilizând:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dAmbele medii împărtășesc aceeași configurație de bază, menținând în același timp setări independente potrivite pentru cerințele lor specifice. Această separare îmbunătățește mentenabilitatea, reduce erorile de configurare și menține alinierea dintre mediile locale și cele de producție.
Depanarea mediului dumneavoastră
Această secțiune oferă pași de depanare pentru problemele comune pe care le puteți întâmpina atunci când rulați aplicația cu Docker Compose.
502 Gateway Greșit (Nginx afișează răspunsuri 502)
Simptome:
- Browserul afișează 502 Bad Gateway când accesează
http://localhost:8000. - Jurnalele Nginx conțin linii precum
recv() failed (111: Connection refused)sauconnect() failed (111: Connection refused) while connecting to upstream.
Cauze probabile:
- PHP-FPM (serviciul
app) nu rulează sau nu ascultă pe socket/portul așteptat. - Nginx
fastcgi_passindică gazda/portul greșit. - Numele containerului nu se potrivește sau există probleme de rețea între
nginxșiapp. apps-a blocat la pornire (de exemplu, din cauza extensiilor lipsă sau a erorilor de configurare).
Cum să confirmați:
Inspectează jurnalele Nginx:
docker compose logs nginx | tail -n 100Caută mesaje
502sau erori de conexiune upstream.Verifică starea și jurnalele containerului
app:docker compose ps app docker compose logs app --tail=200Confirmă că PHP-FPM ascultă în interiorul containerului
app:docker compose exec app ss -ltnp | grep :9000 || docker compose exec app ss -lxp | grep php-fpmAșteptat: fie un ascultător TCP pe portul
9000, fie un socket Unix folosit denginx(mai puțin frecvent cu acest compose).Confirmați că
nginxpoate rezolva și accesaapppe rețeaua compose:docker compose exec nginx ping -c 2 app docker compose exec nginx wget -qO- --timeout=2 http://app:9000/ || trueDacă
pingeșuează sauwgetexpiră, există o problemă de rețea sau o nepotrivire a numelui serviciului.
Remedieri comune:
Dacă PHP-FPM nu rulează, verificați jurnalul
apppentru erori PHP fatale sau eșecuri la pornire. Remediați eroarea de bază (adesea o extensie lipsă sau o problemă de permisiuni) și reporniți:docker compose restart app docker compose logs app --tail=100Dacă configurația Nginx folosește un upstream diferit (de exemplu,
fastcgi_pass 127.0.0.1:9000;), actualizațidocker-compose/nginx/travellist.conflafastcgi_pass app:9000;(potrivind numele serviciului din compose) și reîncărcați Nginx:# After editing config in host docker compose exec nginx nginx -s reload docker compose logs nginx --tail=50Dacă PHP-FPM ascultă pe un socket Unix (de exemplu,
/run/php/php7.4-fpm.sock), dar Nginx se așteaptă la TCP sau invers, standardizați pe TCPapp:9000pentru configurațiile Compose sau montați corect socket-ul între containere (recomandat: folosiți TCP în Compose cu mai multe containere).
Extensii PHP lipsă (erori la rularea Composer sau Artisan, sau eșecuri la execuție)
Simptome:
- Comenzile Composer sau Laravel eșuează cu mesaje de tipul
Class "PDO" not found,ext-pdo is missingsauCall to undefined function json_encode. - Erori PHP în jurnalele
appcare fac referire la clase sau funcții nedefinite.
Cum să confirmați:
Inspectați lista modulelor PHP din containerul
app:docker compose exec app php -m | sortCaută numele extensiilor de care ai nevoie (pentru extensiile tipice Laravel:
pdo_mysql,mbstring,bcmath,openssl,tokenizer,xml,ctype,json,gd).Verificați textul de eroare al composer, care de obicei menționează extensiile necesare:
docker compose exec app composer install
Remedieri:
Adaugă extensiile lipsă în Dockerfile-ul tău și reconstruiește imaginea. Exemplu (pentru
pdo_mysqlșigd):RUN apt-get update && apt-get install -y libpng-dev libxml2-dev \ && docker-php-ext-install pdo_mysql mbstring xml gdApoi reconstruiește și repornește:
docker compose build app docker compose up -d app docker compose logs app --tail=100Dacă o extensie necesită biblioteci de sistem (de exemplu,
gdare nevoie delibpng-dev), adaugă liniile corespunzătoareapt-get installînainte dedocker-php-ext-install.Dacă ai nevoie de o extensie PHP care nu este inclusă implicit, ia în considerare instalarea acesteia prin PECL și activarea ei în
php.ini.
Eșecuri de conectare la baza de date (Laravel nu se poate conecta la MySQL)
Simptome:
- Laravel afișează erori de conectare la baza de date (
SQLSTATE[HY000] [2002] Conexiune refuzatăsauAcces refuzat pentru utilizator). - Migrațiile eșuează sau aplicația afișează o pagină goală pentru paginile bazate pe date.
Cum să confirmați:
Verificați jurnalele containerului DB pentru erori de inițializare:
docker compose logs db --tail=200Verificați dacă containerul DB este pornit:
docker compose ps dbConfirmă că acreditările și gazda sunt consistente între
.envșidocker-compose.yml. În.envdin Laravel,DB_HOSTar trebui să fie numele serviciului din compose (db), nu127.0.0.1saulocalhost:DB_HOST=db DB_PORT=3306 DB_DATABASE=travellist DB_USERNAME=travellist_user DB_PASSWORD=passwordTest din interiorul containerului
db:docker compose exec db mysql -u"${DB_USERNAME}" -p"${DB_PASSWORD}" -e "SHOW DATABASES;"Acum, testează din containerul
apppentru a te asigura de conectivitatea rețelei: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();"'
Cauze și soluții comune:
Gazdă greșită în
.env: actualizațiDB_HOST=db, recreați containerele sau reîncărcați variabilele de mediu:docker compose down docker compose up -d docker compose exec app php artisan migrateBaza de date nu este pregătită când aplicația pornește: folosește un mecanism de reîncercare în aplicația ta sau adaugă un healthcheck și începe procesarea comenzilor. De asemenea, poți aștepta manual:
docker compose exec db mysqladmin -u"${DB_USERNAME}" -p"${DB_PASSWORD}" ping # expected: mysqld is aliveEșec la inițializarea SQL: verificați fișierele din
./docker-compose/mysql, o eroare de sintaxă sau de permisiune poate opri inițializarea bazei de date. Inspectați jurnalele bazei de date pentru erori de import.Privilegii/credite incorecte: confirmați că baza de date și utilizatorul există. Refaceți baza de date sau rulați SQL pentru a acorda privilegii.
Utilizarea portului la nivel de gazdă: dacă ați încercat
curl telnet://localhost:3306și serviciuldbnu expune un port al gazdei, acea conexiune va fi refuzată din motive de design. Testați din interiorul containerelor sau expuneți portul îndocker-compose.yml(ports: - "3306:3306") pentru depanare doar locală.
Probleme de permisiuni și ale sistemului de fișiere (stocare, cache, fișiere jurnal)
Sintome:
- Laravel aruncă excepții legate de scrierea în cache sau în jurnale:
Fluxul sau fișierul "/var/www/storage/logs/laravel.log" nu a putut fi deschis. - Fișierele create de procesele containerului sunt deținute de
rootși nu pot fi modificate de utilizatorul de pe gazdă.
Cum să confirmați:
Verificați permisiunile fișierului de pe gazdă:
ls -l ls -l storage bootstrap/cache docker compose exec app id -u # user id inside containerVerificați jurnalele containerului pentru erori de permisiuni.
Remedieri:
Asigură-te că Dockerfile setează utilizatorul și UID-ul care corespund utilizatorului tău de pe gazdă (Dockerfile-ul tău creează deja un utilizator cu
ARG uid). Confirmă căuiddin argumentele de build dindocker-compose.ymlcorespunde UID-ului tău de pe gazdă (de obicei1000).Remediați proprietatea de la gazdă sau din interiorul containerului:
docker compose exec app chown -R sammy:sammy /var/www/storage /var/www/bootstrap/cachesau de la gazdă:
sudo chown -R $(id -u):$(id -g) storage bootstrap/cachePentru dezvoltare, montările legate pot provoca neconcordanțe de permisiuni; este mai bine să rulezi comenzile din container pentru a ajusta proprietatea după ce pornești containerele.
Erori legate de compozitor sau furnizor
Simptome:
composer installeșuează în interiorulappsau lipsa folderuluivendorcauzează eroarea de clasă negăsită.composerraportează epuizarea memoriei în container.
Cum să confirmați:
Rulează composer în interiorul containerului
appși capturează rezultatul:docker compose exec app composer install --no-interaction --prefer-dist
Remedieri:
Dacă limitele de memorie pentru
composersunt depășite, permiteți mai multă memorie sau setați variabila de mediu a composer:docker compose exec app php -d memory_limit=-1 /usr/bin/composer installAsigurați-vă că executabilul Composer este prezent (Dockerfile-ul dvs. copiază composer). Dacă nu, reconstruiți imaginea cu stratul composer.
Dacă
vendorlipsește din cauza suprapunerii de montare bind, asigură-te că montarea ta bind nu ascunde folderulvendorcreat în imagine. Cea mai bună practică este să rulezicomposer installdupă ce containerele sunt pornite, astfel încâtvendorsă fie creat în folderul montat, sau să adaugivendorîn container prin construirea imaginii pentru producție.
Aplicația returnează o pagină goală sau erori 500
Simptome:
- Browser-ul afișează un răspuns gol sau HTTP 500.
- Jurnalele Nginx arată 200, dar pagina este goală; jurnalele
apparată excepții fatale.
Cum să confirmați:
Inspectează jurnalele aplicației:
docker compose exec app tail -n 200 storage/logs/laravel.log docker compose logs app --tail=200Verifică mediul:
APP_DEBUG=trueîn.envva face ca Laravel să afișeze erori detaliate în dezvoltare (nu activați în producție).
Remedieri:
Remediați excepția de bază afișată în
laravel.log.Asigură-te că
.envexistă și căAPP_KEYeste setat:docker compose exec app php artisan key:generateExecutați migrațiile, goliți memoria 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
Eșecuri la construirea containerelor (erori în timpul docker compose build)
Simptome:
docker compose buildgenerează erori la pașii apt sau build.
Cum să confirmați:
Rulați din nou build-ul cu jurnale:
docker compose build app
Remedieri:
Citește rezultatul pasului care a eșuat. Probleme tipice:
- Rețea/DNS în mediul de construcție: încearcă din nou sau asigură-te că Docker poate accesa internetul.
- Pachete lipsă sau sursă apt greșită: adăugați
apt-get updateînainte de instalări și curățați listele apt după aceea. - Permisiuni asupra fișierelor copiate în imagine: asigurați-vă că rutele
COPYsunt corecte.
Exemplu de fragment Dockerfile pentru instalări robuste:
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/*Probleme de rețea sau DNS între containere
Simptome:
- Un container nu poate ajunge la altul folosind numele serviciului (de exemplu,
appnu poate ajunge ladbprindb:3306). pingdupă numele serviciului eșuează.
Cum să confirmați:
docker compose exec app ping -c 3 db
docker compose exec app getent hosts db
docker network inspect travellistRemedieri:
Confirmă că serviciile partajează aceeași rețea în
docker-compose.yml(ambele ar trebui să facă referire latravellist).Dacă ați schimbat numele serviciilor sau al rețelelor, actualizați corespunzător
DB_HOSTși upstream-urile Nginx.Recreează rețeaua (aceasta distruge containerele efemere, deci fii atent):
docker compose down docker network prune # optional and destructive docker compose up -d
Comenzi de diagnostic utile
Executați acestea pentru inspecție țintită:
Afișați containerele și porturile active:
docker compose psJurnale în timp real pentru un serviciu:
docker compose logs -f --tail=200 nginxExecutați un shell într-un container:
docker compose exec app sh docker compose exec db bashInspectează variabilele de mediu ale containerului:
docker compose exec app env | sort docker compose exec db env | grep MYSQLVerifică lista proceselor din container:
docker compose exec app ps aux docker compose exec app ss -ltnpVerifică starea MySQL:
docker compose exec db mysqladmin -u"${DB_USERNAME}" -p"${DB_PASSWORD}" ping
Când să expui porturile gazdei pentru depanare
Implicit, serviciul db în această configurație nu este legat de porturile gazdă. Expune porturile doar pentru depanarea locală. Pentru a expune temporar MySQL pe gazdă, adaugă în docker-compose.yml sub db:
ports:
- "3306:3306"Apoi repornește:
docker compose up -d dbDupă depanare, eliminați maparea ports pentru a evita expunerea bazei de date la rețea.
Întrebări frecvente
1. Am nevoie de Composer instalat pe gazdă?
Nu. Poți rula Composer complet în interiorul containerului aplicației, ceea ce este abordarea recomandată pentru acest flux de lucru Compose. Dockerfile-ul din tutorial include Composer, așa că rulează comenzi precum docker compose exec app composer install sau docker compose run --rm app composer require vendor/package. Rularea Composer în container asigură utilizarea versiunii și extensiilor PHP corecte și evită crearea fișierelor vendor cu proprietate nepotrivită pe gazdă.
2. Pot rula migrațiile Laravel din interiorul containerului?
Da. Execută migrațiile din containerul aplicației astfel încât să folosească același runtime și aceeași rețea ca aplicația ta: docker compose exec app php artisan migrate. Pentru sarcini unice sau în CI poți folosi docker compose run --rm app php artisan migrate --force. Înainte de a rula migrațiile, asigură-te că containerul bazei de date este sănătos și acceptă conexiuni, de exemplu cu docker compose exec db mysqladmin -u$ {DB_USERNAME} -p$ {DB_PASSWORD} ping sau prin reîncercare până când răspunde.
3. Cum pot instala extensii PHP suplimentare?
Adaugă pachetele de sistem necesare și comenzile pentru extensii în Dockerfile, apoi reconstruiește imaginea. De exemplu, instalează dependențele și construiește extensiile comune cu ceva de genul:
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 gdDacă ai nevoie de o extensie PECL, folosește pecl install și docker-php-ext-enable. După ce editezi Dockerfile-ul, rulează docker compose build app, iar apoi docker compose up -d app pentru a aplica modificările.
4. Cum expun containerul Nginx pentru HTTPS?
Adaugă un bloc de server HTTPS în configurația Nginx, montează certificatul și cheia în container și publică portul 443 în docker-compose. Iată un exemplu cu modificări minimale în docker-compose.yml:
services:
nginx:
ports:
- "8000:80"
- "443:443"
volumes:
- ./docker-compose/nginx:/etc/nginx/conf.d
- ./certs:/etc/nginx/certs:roApoi adaugă un bloc de server SSL care face referire la /etc/nginx/certs/fullchain.pem și /etc/nginx/certs/privkey.pem. Pentru producție, folosește un proxy invers sau un manager de certificate precum Traefik sau un balancer de sarcină extern pentru a obține și reînnoi certificatele în siguranță, în loc să stochezi cheile private în stiva aplicației.
5. Cum îmi reconstruiesc Laravel după modificările din cod?
Depinde de ceea ce s-a schimbat. Dacă folosești bind mounts pentru directorul proiectului, modificările la PHP, template-uri, rute și controlere se reflectă imediat; rulează comenzi de curățare a cache-ului Laravel dacă este nevoie, de exemplu:
docker compose exec app php artisan config:clear
docker compose exec app php artisan route:clear
docker compose exec app php artisan view:clearDacă ați schimbat dependențele Composer sau Dockerfile-ul (noi extensii sau pachete de sistem), reinstalați sau reconstruiți: docker compose exec app composer install pentru schimbări de dependențe și docker compose build app && docker compose up -d pentru schimbări în Dockerfile. Repornirea serviciului afectat este necesară când modificați configurația PHP-FPM sau Nginx: docker compose restart app sau docker compose restart nginx.
Concluzie
În acest ghid, am configurat un mediu Docker cu trei containere folosind Docker Compose pentru a defini infrastructura noastră într-un fișier YAML.
De acum înainte, poți lucra la aplicația ta Laravel fără a fi nevoie să instalezi și să configurezi un server web local pentru dezvoltare și testare. Mai mult, vei lucra cu un mediu temporar care poate fi ușor replicat și distribuit, ceea ce poate fi util atât în timpul dezvoltării aplicației tale, cât și atunci când te muți către un mediu de producție.
Pentru mai multe tutoriale Laravel, consultați următoarele articole:
- Găzduiește-ți aplicația Laravel pe Linux-Console.net
- Cum să instalezi și să configurezi Laravel cu Nginx pe Ubuntu (Stack LEMP)
- Cum să creezi resurse API Laravel Eloquent pentru a transforma modelele în JSON
- Cum să inițializezi o nouă aplicație Laravel cu Docker Compose
Mulțumim că ați învățat împreună cu comunitatea Linux-Console.net.

