Laravel локально поднимается двумя командами — composer install и php artisan serve, — а вот публикация в интернет обычно превращается в отдельную задачу: сервер, нужная версия PHP с расширениями, composer, nginx с корнем в папке public, php-fpm, права на storage и bootstrap/cache, сертификат, база, миграции. Каждый пункт прост сам по себе, а вместе это вечер работы и ещё один — на разбор пустого экрана вместо сайта. На Dockbox эту часть берёт на себя платформа: вы загружаете код, она сама определяет PHP-проект, ставит зависимости по composer.json, собирает проект и выдаёт публичную HTTPS-ссылку. Ниже — что подготовить в проекте, чтобы всё заработало с первого раза.
Почему деплой Laravel превращается в отдельный проект
Привычный путь — длинный чек-лист: арендовать сервер, собрать нужную версию PHP, пройти composer install, настроить php-fpm, поставить перед ним nginx и направить его корень в public, выпустить сертификат, поднять базу и не забыть про миграции.
Версия PHP и расширения. Laravel 11 требует PHP 8.2 или новее и набор расширений — mbstring, openssl, pdo, tokenizer, xml. Не хватает одного — и composer install падает.
Корень сайта. Web-сервер должен смотреть в public, а не в корень проекта: иначе по адресу example.com/.env откроется файл с паролями и APP_KEY, а рядом будет лежать весь storage.
Права на папки. storage и bootstrap/cache должны быть доступны на запись пользователю PHP — иначе сайт отдаёт 500 и в логе Permission denied.
База и миграции. Базу нужно поднять, прописать доступы и прогнать миграции до первого посетителя. Плюс сервер стоит денег все тридцать дней — даже если сайт открывают раз в сутки.
Платформа деплоя снимает эту часть: она видит composer.json, ставит зависимости и отдаёт публичную HTTPS-ссылку.
Шаг 1. composer.json в корне, vendor — не в архив
composer.json в корне проекта — это признак, по которому платформа понимает, что перед ней PHP-проект на Laravel, и по которому ставит зависимости при сборке. Рядом обязателен composer.lock: он фиксирует точные версии пакетов, и без него сборка подтянет более свежие, с которыми проект никто не проверял.
Папку vendor в архив не кладите. Это те же библиотеки, которые платформа поставит сама из composer.lock: лишние десятки мегабайт, долгая загрузка и риск, что локальные версии разойдутся с продом.
Шаг 2. .env не попадает в архив — значения идут в переменные окружения
В .env лежат APP_KEY, пароли к базе, доступы к почте и внешним сервисам. Этот файл не должен оказаться ни в архиве, ни в репозитории: в архиве он едет открытым текстом, а из истории Git его потом не вычистить. Значения переносим в переменные окружения проекта — они хранятся зашифрованными, а Laravel читает их привычным способом через env() и config().
Что именно перенести: APP_KEY, APP_ENV, APP_DEBUG, APP_URL, всё семейство DB_*, MAIL_* и токены внешних API. Типичный набор выглядит так:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=***
В панели видны имена переменных, а значения — никому. Если .env уже лежал в репозитории, считайте секреты утёкшими: смените пароли и перевыпустите APP_KEY.
Шаг 3. APP_KEY, APP_DEBUG=false и production-режим
Без APP_KEY приложение не стартует. Laravel падает на первом же запросе, который касается шифрования, с ошибкой No application encryption key has been specified. Ключ генерируется локально одной командой:
php artisan key:generate --show
Команда печатает строку вида base64:... — её и указывайте значением APP_KEY в настройках проекта.
Отладку выключите до публикации. APP_DEBUG=true в продакшене показывает посетителю стек вызовов, пути к файлам и куски кода, а иногда и строку подключения к базе. Перед публикацией выставьте APP_ENV=production и APP_DEBUG=false.
Шаг 4. Корень — public, порт — из окружения, права на storage
Корень сайта — только public/. Именно там лежит index.php. На платформе корень выставляется сам — нужно лишь не переносить index.php из public.
Порт не хардкодьте. Контейнер слушает тот порт, который даёт платформа, и это единственное место, куда приходит трафик. Если вы запускаете приложение своим процессом через artisan serve, читайте порт из окружения и слушайте 0.0.0.0:
php artisan serve --host=0.0.0.0 --port=$PORT
Жёстко прописанный 127.0.0.1:8000 — причина номер один, по которой приложение работает, а ссылка не открывается.
Права на storage и bootstrap/cache. Laravel пишет туда логи, кэш, сессии и загруженные файлы, поэтому обеим папкам нужен доступ на запись — локально это chmod -R 775 storage bootstrap/cache. Если «Permission denied» вылезает после деплоя, дело почти всегда в правах.
Шаг 5. База данных, миграции и постоянные файлы
Базу можно поднять рядом с приложением — как сервис в docker-compose внутри того же проекта.
services:
app:
build: .
db:
image: mysql:8
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Именованный том у базы обязателен. Без него данные обнуляются при первом же обновлении кода. Второй вариант — внешняя база: указываете её хост, порт и доступы в DB_*.
Миграции выполняются при старте. Терминала внутри проекта нет, поэтому прогонять их нужно из стартовой команды:
php artisan migrate --force
Флаг --force обязателен: в production Laravel спрашивает подтверждение, а в неинтерактивном запуске вопроса не ждёт и миграции не выполняет.
Файлы пользователей — в постоянное хранилище. Симлинк public/storage создаётся командой php artisan storage:link при старте. Всё, что приложение пишет внутрь контейнера, при обновлении кода пересоздаётся: загрузки держите во внешнем S3-совместимом хранилище или на постоянном диске.
Шаг 6. Загрузите код и получите HTTPS-ссылку
Проект попадает на платформу ZIP-архивом или импортом репозитория GitHub. Дальше платформа сама ставит зависимости, собирает и запускает приложение: настраивать nginx, php-fpm и корень public руками не нужно. Логи сборки и запуска видны в панели в реальном времени, поэтому ошибка проявляется сразу, а собственный домен подключается в настройках проекта: записи DNS подсказываются в панели, сертификат выпускается автоматически.
Сколько это стоит и как работают контейнеры
Администрировать сервер не нужно — контейнеры работают постоянно, без ограничения по часам и без «засыпания». Упавший контейнер платформа перезапускает сама.
Starter — 990 ₽/мес. 1 vCPU, 2 GB RAM, первый месяц бесплатный. Для одного Laravel-проекта этого достаточно, и лимита по времени работы у тарифа нет.
Pro — 2 490 ₽/мес. Больше ресурсов и до пяти проектов — если рядом с сайтом живут ещё база, очередь и воркер.
Team — 4 990 ₽/мес — для команд, которым нужен запас ресурсов и SLA.
Тарифы и подробности — на dockbox.host.
Частые вопросы
Нужно ли настраивать nginx и php-fpm?
Нет. Корень в папке public, php-fpm и порт настраиваются автоматически при сборке. От вас нужен код проекта с composer.json, и всё.
Что делать с файлом .env?
Не класть его ни в архив, ни в репозиторий. Значения переносятся в переменные окружения: они хранятся зашифрованными, а Laravel читает их обычным способом. .env в архиве — самый простой способ потерять пароль к базе вместе с APP_KEY.
Как прогнать миграции после деплоя?
Терминала внутри проекта нет, поэтому миграции выполняются автоматически при старте — php artisan migrate --force в стартовой команде. Флаг --force обязателен, иначе Laravel в production ждёт подтверждения и миграции пропускает.
Сайт отдаёт 500 или пустую страницу — с чего начать?
Три частые причины: не задан APP_KEY, нет прав на запись в storage и bootstrap/cache, база недоступна или миграции не прошли. Настоящая ошибка написана в логах запуска — откройте их в панели.
Куда девать файлы, которые загружают пользователи?
Всё, что приложение пишет внутрь контейнера, при обновлении кода пересоздаётся. Если загрузки должны сохраняться, вынесите их во внешнее хранилище либо подключите постоянный диск или именованный том. Симлинк public/storage создаётся командой php artisan storage:link при старте.