Laravel Queue Workers Crashing After Docker Deploy: 5 Quick Fixes for 500 Errors on Nginx in a Production VPS Environment
You’ve just pushed a fresh Docker image to your Ubuntu‑based VPS, hit docker compose up -d, and moments later the Nginx logs start spitting out 500 errors. Your Laravel queue workers die instantly, and the whole API grinds to a halt. It’s the kind of nightmare that makes even seasoned PHP devs want to pull their hair out.
Why This Matters
Queue workers are the backbone of any Laravel SaaS that processes emails, notifications, or API calls asynchronously. When they crash, users experience delays, revenue pipelines stall, and support tickets pile up. In a VPS environment where resources are finite, a mis‑configured Docker or Nginx layer can waste CPU cycles, flood the error log, and mask deeper PHP‑FPM or Redis issues.
Common Causes of 500 Errors After Docker Deploy
- Incorrect
php-fpmpool settings inside the container. - Missing
.envvariables leading to unhandled exceptions. - Supervisor not restarting queue workers after a container restart.
- Redis connection timeout due to Docker network isolation.
- File permission mismatches between host and container volumes.
Step‑By‑Step Fix Tutorial
1️⃣ Align PHP‑FPM Settings with VPS Limits
Open the Dockerfile or your custom php-fpm.conf and ensure the pool matches the VPS CPU/RAM. Example for a 2‑core, 4 GB VPS:
[www]
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 30
pm.start_servers = 6
pm.min_spare_servers = 3
pm.max_spare_servers = 12
php_admin_value[error_log] = /var/log/php-fpm.log
php_admin_flag[log_errors] = on
After editing, rebuild the image and restart:
docker compose build php
docker compose up -d php
2️⃣ Pass All .env Variables to Docker
docker-compose.yml references a host‑mounted .env file or uses environment: blocks for each key.
services:
app:
image: yourcompany/laravel-app:latest
env_file:
- ./.env
volumes:
- ./:/var/www/html
depends_on:
- redis
- db
3️⃣ Configure Supervisor Inside the Container
Supervisor keeps queue workers alive across container restarts. Add a supervisord.conf like this:
[supervisord]
nodaemon=true
[program:laravel-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=3
redirect_stderr=true
stdout_logfile=/var/log/queue.log
Don’t forget to install Supervisor in your Dockerfile:
RUN apt-get update && apt-get install -y supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
4️⃣ Fix Redis Network Bridge
redis, queue workers will throw a 500 error.
Use Docker’s internal DNS by setting an explicit network and alias:
networks:
laravel:
driver: bridge
services:
redis:
image: redis:6-alpine
networks:
laravel:
aliases:
- cache
Then update .env:
REDIS_HOST=cache
REDIS_PASSWORD=null
REDIS_PORT=6379
5️⃣ Harden File Permissions
Docker can mount files with the wrong uid/gid, causing Laravel to fail when writing logs or cache. Run this after container start:
docker exec -it $(docker ps -qf "name=app") bash -c "
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache;
chmod -R 775 /var/www/html/storage /var/www/html/bootstrap/cache"
VPS or Shared Hosting Optimization Tips
- Swap Management: Disable swap on production VPS to avoid latency spikes (
sudo swapoff -a). - OPcache: Enable
opcache.enable=1and setopcache.memory_consumption=256for fast PHP execution. - MySQL Tuning: Use
innodb_buffer_pool_size=70% RAMandmax_connections=500for high‑throughput APIs. - Cloudflare Caching: Cache static assets at edge, but bypass
/api/*routes. - System Monitoring: Set up
htop,netdataor New Relic to catch resource saturation early.
Real World Production Example
Acme SaaS runs a 8‑core, 16 GB VPS on Ubuntu 22.04. After a rushed Docker rollout, the queue:work processes crashed, generating 1,200 500 errors per minute. Applying the five steps above reduced error rate to zero within 10 minutes. CPU usage dropped from 95% to 42% because PHP‑FPM pools were finally respecting pm.max_children.
Before vs After Results
| Metric | Before | After |
|---|---|---|
| 500 Errors/min | 1,200 | 0 |
| CPU Utilization | 95% | 42% |
| Queue Lag | 45s | 3s |
Security Considerations
- Never expose
APP_DEBUG=truein production – it leaks stack traces. - Use
docker secretsorVaultfor database passwords instead of plain.envfiles. - Limit Supervisor to run as
www-data, not root. - Apply Nginx
limit_reqandlimit_connto protect against DDoS spikes. - Enable
HTTP Strict Transport Security (HSTS)and TLS 1.3 in your Nginx block.
Bonus Performance Tips
- Cache Heavy Queries: Use Redis
Cache::remember()with a 10‑minute TTL. - Queue Prioritization: Separate high‑priority jobs into a dedicated
highqueue with more workers. - Lazy Loading Avoidance: Eager load relationships (
with()) for API endpoints that hit the DB heavily. - Static Asset CDN: Offload
/public/cssand/jsto Cloudflare or Amazon S3. - Composer Optimize: Deploy with
composer install --no-dev --optimize-autoloader.
FAQ
Q: My queue still restarts after a Docker image update. What gives?
A: Ensure Supervisor is running as PID 1 in the container or use Docker’s --restart unless-stopped flag combined with docker compose up -d to keep the service alive.
Q: Do I need a separate Redis container for each Laravel app?
No. A single Redis instance can host multiple databases; just set REDIS_DB per app.
Q: How can I monitor queue health without a paid SaaS?
Use php artisan queue:failed and a simple cron that pings /health. Pair it with netdata for real‑time graphs.
Final Thoughts
Docker is a fantastic tool, but when you combine it with a tightly‑packed VPS, missing a single environment variable or mis‑sizing PHP‑FPM can cascade into massive 500 storms. The five fixes above give you a repeatable, version‑controlled checklist that keeps Laravel queue workers alive, Nginx happy, and your users paying.
If you’re looking for a low‑cost, high‑performance hosting partner that already ships with optimized PHP‑FPM, Redis, and MySQL on a managed VPS, check out cheap secure hosting. Their one‑click Docker installer and built‑in Cloudflare CDN can shave milliseconds off every request.
No comments:
Post a Comment