Laravel Queue Timeouts in Docker: Find the Killer
The calculator for this page is switched off while it is checked. The formula is below, and the worked example in the article shows how to use it by hand.
This article helps you diagnose why your Laravel queue worker keeps dying inside a Docker container, and it gives you a clear method to find the culprit. The most common killers are PHP’s `max_execution_time` (which doesn’t apply to CLI but can be set by a custom ini), the queue worker’s own `–timeout` option, and Docker’s default stop timeout sending SIGKILL after 10 seconds. We’ll walk through the exact commands to check each one and how to fix them.
Background: How Laravel Queue Workers Work
Laravel’s queue worker is a long-running PHP process. When you run `php artisan queue:work`, it starts a loop that listens for jobs, processes them one by one, and then waits for the next. The worker is designed to run indefinitely, but several layers can kill it: the PHP process itself, the queue worker’s own timeout, or the Docker container’s lifecycle. In a Docker setup, you typically run the worker as the container’s main process (CMD or ENTRYPOINT), so when that process exits, the container stops. Understanding which layer is killing your worker is the first step to fixing it.
How to Check What’s Killing the Worker
Start by looking at the worker’s logs. If you’re using `supervisord` or a similar process manager inside the container, check its logs. If not, run the worker in the foreground (without `-d` or `–daemon`) and watch the output. The most direct way is to add logging to your job’s `failed()` method or use the `queue:failed` table. But for a sudden death with no error, the usual suspects are:
- PHP `max_execution_time` – This is a CLI setting, but if you have a custom `php.ini` that sets it, it will kill the worker after that many seconds. By default, CLI has it set to 0 (unlimited), but many Docker images set it to 30 or 60.
- Laravel’s `–timeout` option – This is the number of seconds a job can run before the worker kills it. It’s not the worker’s lifetime; it’s per-job. If a job runs longer than this, the worker will terminate the process.
- Docker’s stop timeout – When you run `docker stop`, Docker sends SIGTERM, waits 10 seconds (default), then sends SIGKILL. If your worker doesn’t handle SIGTERM gracefully, it will be killed.
Step-by-Step Diagnosis
- Check PHP’s max_execution_time: Run `php -i | grep max_execution_time` inside the container. If it’s not 0, set it to 0 in your `php.ini` (CLI section) or via `-d max_execution_time=0` in your command.
- Check the worker’s timeout: Look at your `queue:work` command. If you have `–timeout=60`, that’s per-job. If a job takes longer, the worker kills it. Increase it or set it to 0 (no limit) if you trust your jobs.
- Check Docker’s stop signal: If you’re using `docker stop`, the container gets SIGTERM. Laravel’s worker does not handle SIGTERM by default, so it dies immediately. Use `–stop-when-empty` or a process manager like `supervisord` to handle graceful shutdown.
- Look at the logs: Add a `Log::info(‘Job started’)` at the beginning of your job and `Log::info(‘Job ended’)` at the end. If you see ‘started’ but not ‘ended’, the job is being killed mid-execution.
- Check memory limits: `memory_limit` can also kill a worker if a job uses too much memory. Run `php -i | grep memory_limit` and increase if needed.
Common Problems and Their Fixes
- Worker exits after a few seconds: This is usually PHP’s `max_execution_time`. Fix: set it to 0 for CLI.
- Worker dies after a long job: This is likely the `–timeout` option. Fix: increase it or set to 0.
- Worker dies when you run `docker stop`: This is Docker’s SIGTERM. Fix: use a process manager or handle SIGTERM in your worker.
- Worker dies randomly with no log: Check memory limit and also check if the container is being OOM-killed by the host. Use `docker inspect` to see exit code 137 (SIGKILL).
Comparisons: Docker vs. Bare Metal
In a bare-metal setup, you might use `supervisord` or `systemd` to keep the worker alive. In Docker, the same applies, but you also have the container’s lifecycle to consider. Docker’s default `STOPSIGNAL` is SIGTERM, and the default timeout is 10 seconds. If your worker doesn’t handle SIGTERM, it will be killed immediately. Many people use `supervisord` inside the container to manage the worker and restart it if it dies. Alternatively, you can use `–stop-when-empty` to let the worker finish current jobs and then exit gracefully.
How to Choose the Right Timeout Values
Choosing timeouts depends on your job’s expected duration. If you have jobs that take up to 2 minutes, set `–timeout=180` to give a buffer. For PHP’s `max_execution_time`, keep it at 0 for CLI. For Docker’s stop timeout, you can change it with `docker stop -t 30` or set `STOPSIGNAL` in the Dockerfile. The key is to make the timeout slightly longer than the longest job, but not so long that a stuck job hangs forever.
Safety and Best Practices
- Always set a `–timeout` for your worker to prevent stuck jobs from running forever.
- Use a process manager like `supervisord` to restart the worker if it crashes.
- Monitor your worker’s memory usage and set a `memory_limit` that is high enough for your jobs.
- Test your worker’s shutdown behavior by sending SIGTERM and seeing if it finishes the current job.
Frequently Asked Questions
Why does my worker die after exactly 60 seconds?
That’s likely the `–timeout=60` option. The worker kills the job after 60 seconds, and if the job doesn’t handle the `WorkerStopping` event, the worker exits. Increase the timeout or set it to 0.
Does `max_execution_time` affect CLI scripts?
By default, no. PHP CLI has `max_execution_time=0`. But if your Docker image includes a custom `php.ini` that sets it, it will apply. Check with `php -i`.
How do I gracefully stop a queue worker in Docker?
Use `php artisan queue:work –stop-when-empty` so the worker finishes current jobs and then exits. Or use `supervisord` to handle SIGTERM and stop the worker gracefully.
What is exit code 137?
Exit code 137 means the process was killed by SIGKILL (128 + 9). This often happens when Docker’s stop timeout is reached or when the host’s OOM killer kills the container. Check `docker inspect` for the exit code.
Can I run multiple workers in one container?
Yes, but it’s not recommended. Use one container per worker, or use a process manager like `supervisord` to run multiple `queue:work` processes. Each worker needs its own memory and CPU.
Why does my worker stop when I deploy?
If you’re using `php artisan queue:restart`, it will stop all workers after the current job. That’s normal. But if it stops without that, check if your deployment script sends a signal to the container.
Related
Formula used
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.