Тема
Деплой и эксплуатация
Прод отличается от dev не кодом, а дисциплиной вокруг него: порядок деплоя, наблюдаемость, бэкапы. Здесь — минимальный набор, который избавляет от «ночных» инцидентов.
Канонический порядок деплоя
Порядок важен: нарушение = битые запросы во время выката.
composer install --no-dev --optimize-autoloader- Сборка фронта (
npm run buildв контейнере — версии Node на хосте не совпадают) php artisan migrate --forcephp artisan optimize(config + route + view + event)php artisan storage:link(идемпотентно, но забывается на новых серверах)php artisan queue:restart— обязательно: воркеры держат старый код в памяти- Прогрев: запрос главной/ключевых страниц (заполняет opcache и кеши)
Для мажорных изменений схемы БД — php artisan down --render=... до, up после; для остального maintenance mode не нужен.
Миграции на проде — правила безопасности
migrate --forceв деплое — да;migrate:fresh/migrate:refreshна проде — никогда (сносят данные).- Разрушающие изменения (drop/rename столбца) — в два релиза: сначала код перестаёт использовать, потом отдельной миграцией удаление. Откат кода не должен требовать отката схемы.
- Большие таблицы — CONCURRENTLY-индексы и правила из спецификации миграций.
- Перед рискованной миграцией —
migrate --pretend(посмотреть SQL) и свежий бэкап.
Health-чеки и мониторинг
| Уровень | Инструмент | Что даёт |
|---|---|---|
| Жив ли процесс | /up (health route из коробки) | Для Caddy/watchdog/докера |
| Живы ли зависимости | spatie/laravel-health | БД, Redis, диск, очередь, cron — одним endpoint'ом |
| Выполняется ли cron | spatie/laravel-schedule-monitor | «Молчаливо умерший» scheduler — частая скрытая авария |
| Не растёт ли очередь | queue:monitor в cron | Алерт до того, как пользователи заметят |
| Ошибки в реальном времени | Sentry (free tier) / laravel-boost__last-error | Стектрейсы с контекстом, группировка |
| Метрики прода | Pulse | Медленные запросы/джобы без внешней инфраструктуры |
| Доступность снаружи | Внешний uptime-чекер | Изнутри сервера свой сайт проверять нельзя (VPN-петля — правило студии) |
Минимум для каждого прод-проекта студии: /up + schedule-monitor + внешний uptime + Telegram-канал алертов.
Бэкапы
- spatie/laravel-backup: БД + файлы по расписанию, уведомление о сбое в Telegram — сбойнувший молча бэкап хуже отсутствующего.
- Хранить минимум в двух местах (локально + S3-совместимое хранилище).
- Бэкап без проверки восстановления — не бэкап. Раз в квартал: развернуть дамп в пустую БД, убедиться что приложение поднимается.
- Перед ETL/массовыми операциями — внеплановый снапшот (правило из инцидентов студии).
Логи
- Канал
dailyс ротацией (14 дней), уровень прода —warning/error;debugв проде = гигабайты шума. Context::add()(request_id, user_id, order_id) — сквозной контекст во всех записях, инцидент разбирается за минуты вместо часов.- Логи контейнеров — с
max-size(в студийном compose уже так), иначе диск кончится. - Смотреть:
laravel-boost__read-log-entries/pail— неtailвслепую.
Очереди и cron в проде
- Отдельные контейнеры
queueиscheduler(по спецификации Docker),restart: unless-stopped. - Воркеры со
--max-time=3600— перезапуск по времени страхует от утечек памяти. failed_jobsразбирать: алерт при росте,queue:retryпосле фикса причины.- Horizon — когда очередей/воркеров больше пары: балансировка и дашборд.
Секреты и конфигурация
.envвне git;.env.example— всегда актуален (новая переменная = сразу в example).- Ключи API — по окружениям: тестовые ключи платёжек в dev, боевые только в prod.
- Ротация при увольнении/утечке: список «какие секреты где» держать в доке проекта.
APP_KEY— в менеджере паролей студии: без него шифрованные данные невосстановимы.
Обновления зависимостей
| Ритм | Действие |
|---|---|
| Еженедельно | composer outdated --direct — глазами; патчи ставить сразу |
| Ежемесячно | composer update минорных + прогон тестов |
| Перед новым мажором Laravel | Rector + laravel-shift ускоряют; ждать 1–2 патч-релиза мажора |
| По CVE | composer audit — в CI/чеклист; критичное — немедленно |
Отставание на 2+ мажора превращает апгрейд в проект — дешевле обновляться ритмично.
Чеклист «проект уходит в прод впервые»
- [ ]
APP_DEBUG=false,APP_ENV=production, боевойAPP_KEYсохранён - [ ] HTTPS + trustProxies (Caddy), редирект http→https
- [ ] Кеш/сессии/очереди — Redis
- [ ]
/up+ внешний uptime-мониторинг + Telegram-алерты - [ ] spatie/backup настроен, восстановление проверено
- [ ] queue + scheduler контейнеры работают,
schedule:listсовпадает с ожиданиями - [ ] Sentry/лог-алерты подключены
- [ ]
robots.txtбоевой (не Disallow всего сайта — частая забытая заглушка!) - [ ] Sitemap генерится, 301-карта старых URL работает
- [ ] Тестовые данные/сидеры не попали в прод-БД
- [ ] Права на
storage/иbootstrap/cache/ - [ ] Деплой-скрипт повторяем одной командой (не «по памяти»)
Чеклист «инцидент на проде»
laravel-boost__last-error/ Sentry — что именно падает.php artisan about— окружение в порядке? кеши актуальны?- Логи за период (
read-log-entries), метрики Pulse. - Очередь жива?
queue:monitor,failed_jobs. - Диск/память/БД:
docker stats, состояние PostgreSQL. - После фикса — post-mortem одним абзацем в доку проекта: причина, защита от повтора.