Воркер - окремий контейнер з тим самим образом, але іншою командою:
services:
queue:
image: myapp:1.4.0
command: php artisan queue:work redis --queue=high,default --tries=3 --max-jobs=1000 --max-time=3600
restart: unless-stopped
stop_grace_period: 60s
Чому окремий контейнер:
- масштабується незалежно:
docker compose up -d --scale queue=4; - важка задача не забирає ресурси у вебзапитів;
- падіння воркера не впливає на сайт, а Docker перезапускає його сам (
restart), тож Supervisor усередині не потрібен.
Чому queue:work треба перезапускати після деплою:
queue:work - довгоживучий процес: він завантажує застосунок один раз і тримає код у пам'яті. Після оновлення файлів старий воркер продовжує виконувати старий код.
- на звичайному сервері
php artisan queue:restartставить мітку в кеш, і воркери завершуються після поточної задачі (а Supervisor запускає їх заново); - у Docker код у контейнері не змінюється - деплой нової версії означає новий образ і нові контейнери. Старі контейнери зупиняються, нові стартують з новим кодом.
queue:restartу такому разі не обов'язковий, але корисний, якщо воркери живуть довше за деплой.
Коректна зупинка:
docker stopнадсилає SIGTERM - воркер Laravel завершує поточну задачу і виходить;- через
stop_grace_period(за замовчуванням 10 секунд) Docker надсилає SIGKILL - задача обривається посередині. Цей час має бути більшим за найдовшу задачу; - щоб сигнал дійшов, PHP має бути PID 1 (
execу скрипті запуску чи exec-формаcommand).
Від витоків пам'яті: --max-jobs і --max-time змушують воркер періодично завершуватися, а Docker його перезапускає з чистою пам'яттю. Для --memory враховуйте ліміт пам'яті контейнера.
Horizon - замість кількох queue:work один контейнер з php artisan horizon, який сам керує процесами за конфігурацією й балансує їх між чергами. Після деплою - horizon:terminate чи заміна контейнера.