Як розгорнути Laravel у Docker

Коли я вперше зіткнувся з необхідністю розгорнути Laravel-проєкт на новій машині, витратив цілий день на налаштування PHP, Composer, MySQL та всіх залежностей. Пішов скороченийм шляхом – спробував запустити Laravel-проєкт у Docker, думав: “Навіщо ускладнювати життя, якщо Laravel Sail уже все робить за мене?”, проте і тут за кілька місяців стикнувся з маштабуваннням в продакшені і вирішив розібратись, як це працює під капотом. Якби тоді я знав про Docker, все було б набагато простіше. Контейнеризація — це не просто модний тренд, а реальний спосіб уникнути класичної проблеми “а в мене не працює”.

Сьогодні розповім, як правильно налаштувати Laravel у Docker, щоб ваше середовище розробки було ідентичним продакшену, а колеги могли запустити проєкт однією командою.

Чому варто використовувати Docker для Laravel

Перш ніж занурюватися в технічні деталі, давайте розберемося, навіщо взагалі Laravel контейнеризація для Laravel-додатків. За кілька років роботи з різними проєктами я виділив кілька ключових переваг, які реально впливають на продуктивність команди.

Docker ізолює ваш додаток разом із усіма залежностями в окремі контейнери. Це означає, що версія PHP, MySQL, Redis та інших сервісів буде однаковою на всіх машинах — від локального ноутбука джуніора до продакшн-сервера. Не потрібно більше годинами налаштовувати оточення для нового члена команди або боятися, що після оновлення системи щось перестане працювати.

Ще один важливий момент — масштабованість. Коли ваш проєкт росте, легко додати нові сервіси: черги, кеш-сервери, Elasticsearch чи що завгодно інше. Просто описуєте новий контейнер у docker-compose.yml, і готово.

Але чесно кажучи, є й мінуси. Docker споживає більше ресурсів порівняно з нативною установкою, особливо на Windows і macOS через віртуалізацію. Також крива навчання досить крута — спочатку доведеться розібратися з Dockerfile, docker-compose, мережами та volumes. Але вірте мені, воно того варте.

Встановлення Docker та необхідних інструментів

Перше, що потрібно зробити — встановити Docker Desktop. Завантажте його з офіційного сайту Docker і встановіть відповідно до інструкцій для вашої операційної системи. Після встановлення перевірте, чи все працює:

docker --version
docker-compose --version

Якщо команди виконуються без помилок — чудово, можемо рухатися далі. Для роботи з Laravel також знадобиться Git та текстовий редактор. Я особисто віддаю перевагу VS Code з розширенням Docker, яке додає підсвічування синтаксису та автодоповнення для Dockerfile.

Створення Dockerfile для Laravel

Тепер перейдемо до найцікавішого — створення 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 безпосередньо з офіційного образу, що набагато швидше, ніж встановлювати його вручну.

Контейнер Composer у Docker

Налаштування docker-compose.yml

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 — це спосіб зв’язати файли на вашій машині з файлами всередині контейнера. Завдяки цьому зміни у коді відразу відображаються в контейнері без перезбирання образу.

Конфігурація Nginx

Створіть директорію 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: крок за кроком

Тепер, коли вся конфігурація готова, час запустити проєкт. Якщо у вас вже є 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 файлу

Скопіюйте .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.

Робота з Artisan командами в Docker

У звичайному оточенні ми запускаємо команди 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 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 — це не просто інструмент, а фундамент для стабільної та ефективної розробки.

Рекомендуємо прочитати

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *