Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124


Коли я вперше зіткнувся з необхідністю розгорнути Laravel-проєкт на новій машині, витратив цілий день на налаштування PHP, Composer, MySQL та всіх залежностей. Пішов скороченийм шляхом – спробував запустити Laravel-проєкт у Docker, думав: “Навіщо ускладнювати життя, якщо Laravel Sail уже все робить за мене?”, проте і тут за кілька місяців стикнувся з маштабуваннням в продакшені і вирішив розібратись, як це працює під капотом. Якби тоді я знав про Docker, все було б набагато простіше. Контейнеризація — це не просто модний тренд, а реальний спосіб уникнути класичної проблеми “а в мене не працює”.
Сьогодні розповім, як правильно налаштувати Laravel у Docker, щоб ваше середовище розробки було ідентичним продакшену, а колеги могли запустити проєкт однією командою.
Перш ніж занурюватися в технічні деталі, давайте розберемося, навіщо взагалі Laravel контейнеризація для Laravel-додатків. За кілька років роботи з різними проєктами я виділив кілька ключових переваг, які реально впливають на продуктивність команди.
Docker ізолює ваш додаток разом із усіма залежностями в окремі контейнери. Це означає, що версія PHP, MySQL, Redis та інших сервісів буде однаковою на всіх машинах — від локального ноутбука джуніора до продакшн-сервера. Не потрібно більше годинами налаштовувати оточення для нового члена команди або боятися, що після оновлення системи щось перестане працювати.
Ще один важливий момент — масштабованість. Коли ваш проєкт росте, легко додати нові сервіси: черги, кеш-сервери, Elasticsearch чи що завгодно інше. Просто описуєте новий контейнер у docker-compose.yml, і готово.
Але чесно кажучи, є й мінуси. Docker споживає більше ресурсів порівняно з нативною установкою, особливо на Windows і macOS через віртуалізацію. Також крива навчання досить крута — спочатку доведеться розібратися з Dockerfile, docker-compose, мережами та volumes. Але вірте мені, воно того варте.
Перше, що потрібно зробити — встановити Docker Desktop. Завантажте його з офіційного сайту Docker і встановіть відповідно до інструкцій для вашої операційної системи. Після встановлення перевірте, чи все працює:
docker --version
docker-compose --versionЯкщо команди виконуються без помилок — чудово, можемо рухатися далі. Для роботи з Laravel також знадобиться Git та текстовий редактор. Я особисто віддаю перевагу VS Code з розширенням Docker, яке додає підсвічування синтаксису та автодоповнення для Dockerfile.
Тепер перейдемо до найцікавішого — створення Dockerfile для Laravel. Це файл, який описує, як буде побудовано образ вашого додатку. Створіть файл з назвою Dockerfile у корені проєкту:
# Використовуємо офіційний образ PHP з FPM
FROM php:8.4-fpm
# Встановлюємо системні залежності
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Очищуємо кеш
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Встановлюємо PHP розширення
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Встановлюємо Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Створюємо користувача для Laravel
RUN useradd -G www-data,root -u 1000 -d /home/laraveluser laraveluser
RUN mkdir -p /home/laraveluser/.composer && \
chown -R laraveluser:laraveluser /home/laraveluser
# Встановлюємо робочу директорію
WORKDIR /var/www
# Копіюємо файли проєкту
COPY --chown=laraveluser:laraveluser . /var/www
# Перемикаємося на користувача
USER laraveluser
EXPOSE 9000
CMD ["php-fpm"]Code language: PHP (php)Давайте розберемо, що тут відбувається. Спочатку ми беремо базовий образ PHP 8.4 з FPM (FastCGI Process Manager). Це важливо, бо саме FPM використовується у зв’язці з Nginx для обробки PHP-запитів. Далі встановлюємо необхідні системні пакети — git для роботи з репозиторіями, libpng-dev для обробки зображень тощо (PHP Docker).
Особлива увага — створення окремого користувача laraveluser. Це важливо з точки зору безпеки, адже запускати додаток від root — погана практика. Ми також копіюємо Composer безпосередньо з офіційного образу, що набагато швидше, ніж встановлювати його вручну.


Dockerfile описує один контейнер, але для повноцінної роботи Laravel потрібно кілька сервісів: веб-сервер, база даних, можливо Redis. Саме тут на допомогу приходить Docker Compose. Створіть файл docker-compose.yml:
version: '3.8'
services:
# Контейнер PHP-FPM
app:
build:
context: .
dockerfile: Dockerfile
image: laravel-app
container_name: laravel-app
restart: unless-stopped
working_dir: /var/www
volumes:
- ./:/var/www
networks:
- laravel
# Nginx веб-сервер
nginx:
image: nginx:alpine
container_name: laravel-nginx
restart: unless-stopped
ports:
- "8000:80"
volumes:
- ./:/var/www
- ./docker/nginx:/etc/nginx/conf.d
networks:
- laravel
# MySQL база даних
mysql:
image: mysql:8.0
container_name: laravel-mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: secret
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
volumes:
- mysql-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- laravel
# Redis для кешування
redis:
image: redis:alpine
container_name: laravel-redis
restart: unless-stopped
ports:
- "6379:6379"
networks:
- laravel
networks:
laravel:
driver: bridge
volumes:
mysql-data:
driver: localCode language: PHP (php)Ця конфігурація створює чотири контейнери, які працюють разом. Контейнер app збирається з нашого Dockerfile і містить Laravel-додаток (Laravel контейнеризація). Nginx виступає як веб-сервер, який приймає HTTP-запити на порту 8000 і передає їх PHP-FPM. MySQL зберігає дані у volume, що означає — навіть після видалення контейнера ваша база залишиться цілою.
Зверніть увагу на volumes — це спосіб зв’язати файли на вашій машині з файлами всередині контейнера. Завдяки цьому зміни у коді відразу відображаються в контейнері без перезбирання образу.
Створіть директорію docker/nginx і додайте туди файл default.conf:
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;
}
}Code language: PHP (php)Цей конфіг каже Nginx слухати на 80 порту і передавати всі PHP-запити на контейнер app через порт 9000. Директива try_files реалізує красиві URL-адреси Laravel без index.php у шляху.
Тепер, коли вся конфігурація готова, час запустити проєкт. Якщо у вас вже є Laravel-додаток — чудово. Якщо ні, створимо новий прямо в контейнері. Спочатку збудуємо образи:
docker-compose buildЦей процес може зайняти кілька хвилин при першому запуску, адже Docker завантажує базові образи та встановлює всі залежності. Після успішної збірки запускаємо контейнери:
docker-compose up -dПрапорець -d означає detached mode — контейнери запускаються у фоні. Перевірте статус:
docker-compose psУсі сервіси повинні бути у статусі Up. Якщо щось пішло не так, дивіться логи:
docker-compose logs app
docker-compose logs nginxТепер встановимо залежності Laravel. Якщо проєкт новий, створимо його:
docker-compose exec app composer create-project laravel/laravel .Або просто встановимо залежності існуючого проєкту:
docker-compose exec app composer installНе забудьте налаштувати права доступу до директорій storage та bootstrap/cache:
docker-compose exec app chmod -R 775 storage bootstrap/cacheСкопіюйте .env.example у .env і відредагуйте параметри підключення до бази:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
CACHE_DRIVER=redis
SESSION_DRIVER=redis
REDIS_HOST=redis
REDIS_PORT=6379Важливо: DB_HOST має збігатися з ім’ям сервісу у docker-compose.yml. Docker автоматично створює внутрішню мережу, де контейнери знаходять один одного за іменами.
Згенеруйте ключ додатку:
docker-compose exec app php artisan key:generateCode language: CSS (css)І запустіть міграції:
docker-compose exec app php artisan migrateВідкрийте браузер і перейдіть на http://localhost:8000. Якщо все налаштовано правильно, побачите стартову сторінку Laravel.
У звичайному оточенні ми запускаємо команди Laravel через php artisan. У Docker це трохи інакше — потрібно вказати, в якому контейнері виконувати команду. Загальний синтаксис виглядає так:
docker-compose exec app php artisan [команда]Code language: CSS (css)Наприклад, створення контролера:
docker-compose exec app php artisan make:controller UserControllerCode language: CSS (css)Або очищення кешу:
docker-compose exec app php artisan cache:clear
docker-compose exec app php artisan config:clearCode language: CSS (css)Щоб не писати щоразу довгу команду, можна створити alias у вашому .bashrc або .zshrc:
alias dartisan='docker-compose exec app php artisan'Code language: JavaScript (javascript)Тепер просто пишіть dartisan migrate замість повної команди. Це справжня економія часу, повірте.
За час роботи з Docker я зіткнувся з купою дрібних проблем, які можуть збити з пантелику. Найчастіша — помилка прав доступу до storage. Якщо бачите Permission denied, виконайте:
docker-compose exec app chown -R www-data:www-data storage bootstrap/cache
docker-compose exec app chmod -R 775 storage bootstrap/cacheІнколи контейнери не можуть з’єднатися з базою даних. Перевірте, чи запущений MySQL-контейнер і чи правильно вказано DB_HOST у .env. Пам’ятайте — це не localhost, а ім’я сервісу з docker-compose.yml.
Якщо зміни у коді не відображаються, спробуйте перезапустити контейнери:
docker-compose restart app nginxІноді Docker споживає забагато дискового простору через старі образи та volumes. Очистити все можна командою:
docker system prune -a --volumesБудьте обережні — ця команда видалить всі невикористовувані образи, контейнери та volumes.
Конфігурація, яку ми створили, чудово підходить для розробки, але для продакшн-середовища потрібні додаткові налаштування. По-перше, не монтуйте весь код через volumes — це знижує продуктивність. Натомість копіюйте файли безпосередньо в образ під час збірки.
По-друге, використовуйте багатоступеневу збірку (multi-stage build) у Dockerfile. Це дозволяє створити мінімальний фінальний образ без зайвих інструментів розробки. По-третє, завжди кешуйте конфігурацію та роути:
docker-compose exec app php artisan config:cache
docker-compose exec app php artisan route:cache
docker-compose exec app php artisan view:cacheCode language: CSS (css)Не забувайте про HTTPS — у продакшені використовуйте Nginx з SSL-сертифікатами. Можна застосувати Let’s Encrypt для безкоштовних сертифікатів.
Якщо весь цей процес здається занадто складним, є простіша альтернатива — Laravel Sail. Це офіційне рішення від команди Laravel, яке надає готову Docker-конфігурацію з коробки. Встановити його просто:
composer require laravel/sail --dev
php artisan sail:installCode language: JavaScript (javascript)Sail автоматично створює docker-compose.yml з усіма необхідними сервісами. Запускається командою:
./vendor/bin/sail upПлюс Sail у тому, що він підтримується офіційно і регулярно оновлюється. Мінус — менше гнучкості для складних конфігурацій. Більше деталей шукайте в офіційній документації Laravel.
Наостанок поділюся набором команд, які я використовую кожного дня. Запуск контейнерів:
docker-compose up -dЗупинка контейнерів:
docker-compose downПерегляд логів у реальному часі:
docker-compose logs -f appПідключення до контейнера через bash:
docker-compose exec app bashПерезбірка образів після змін у Dockerfile:
docker-compose build --no-cache
docker-compose up -dПідключення до MySQL для виконання SQL-запитів:
docker-compose exec mysql mysql -u laravel -pВстановлення нових Composer пакетів:
docker-compose exec app composer require vendor/packageCode language: JavaScript (javascript)Оновлення всіх залежностей:
docker-compose exec app composer updateЗапуск тестів:
docker-compose exec app php artisan testСтворення бекапу бази даних:
docker-compose exec mysql mysqldump -u laravel -p laravel > backup.sqlCode language: CSS (css)Відновлення бази з бекапу:
docker-compose exec -T mysql mysql -u laravel -p laravel < backup.sqlCode language: CSS (css)Запуск Laravel queue worker:
docker-compose exec app php artisan queue:workCode language: CSS (css)Очищення всіх кешів одночасно:
docker-compose exec app php artisan optimize:clearCode language: CSS (css)Моніторинг використання ресурсів контейнерами:
docker statsПерегляд всіх запущених контейнерів проєкту:
docker-compose psРестарт окремого сервісу без зупинки інших:
docker-compose restart appВидалення всіх зупинених контейнерів та невикористовуваних образів:
docker system prune -aКопіювання файлів з контейнера на хост:
docker cp laravel-app:/var/www/storage/logs/laravel.log ./local-logs/Code language: JavaScript (javascript)Копіювання файлів з хоста в контейнер:
docker cp ./config.php laravel-app:/var/www/config/Code language: JavaScript (javascript)Перегляд інформації про конкретний контейнер:
docker inspect laravel-appЦі команди допоможуть швидко діагностувати проблеми та керувати контейнерами без зайвих зусиль. Збережіть їх собі у файл aliases.sh або додайте до вашої конфігурації shell для швидкого доступу. Особисто я створив окремий файл docker-shortcuts.sh у домашній директорії з усіма алясами — це економить купу часу щодня.
Для ще більшої зручності можна створити Makefile у корені проєкту:
.PHONY: up down restart logs shell migrate test cache-clear
up:
docker-compose up -d
down:
docker-compose down
restart:
docker-compose restart
logs:
docker-compose logs -f app
shell:
docker-compose exec app bash
migrate:
docker-compose exec app php artisan migrate
test:
docker-compose exec app php artisan test
cache-clear:
docker-compose exec app php artisan optimize:clearCode language: CSS (css)Тепер замість довгих команд просто пишіть make up, make logs чи make test. Це особливо зручно для нових членів команди, яким не потрібно запам’ятовувати всі docker-compose команди.
Розгортання Laravel у Docker — це інвестиція часу, яка окупається багаторазово. Ви отримуєте передбачуване середовище, просте масштабування та можливість легко онбордити нових розробників. Так, спочатку може здатися складно, але після кількох проєктів це стає другою натурою.
Я пройшов цей шлях від повного нерозуміння Docker до щоденного використання у всіх проєктах. Головне — не боятися експериментувати і читати документацію. Почніть з простої конфігурації, яку ми розглянули, і поступово адаптуйте її під свої потреби.
Якщо у вас виникнуть питання чи проблеми, спільнота Docker і Laravel завжди готова допомогти. Діліться досвідом, вчіться на помилках інших і не забувайте документувати свої рішення для команди. Правильно налаштований Docker — це не просто інструмент, а фундамент для стабільної та ефективної розробки.