I'm trying to run the following command after the container is up and running.
php artisan queue:work -n -q &
The "&" is there because the daemon option was deprecated and later removed from Laravel.
However, this breaks my container startup completely.
CMD ["php", "artisan", "queue:work", "-n", "-q", "&"]
How should I do this in a Docker way?
EDIT:
Using docker-compose I added this line to my docker-compose.yml file
command: bash -c 'php artisan queue:work -n -q;'
The container started but did not serve any requests :S
Using this:
command: bash -c 'php artisan queue:work -n -q &; echo "runs"; tail -f /dev/null'
The container stopped after starting up
Final solution
So in the end I thought that maybe the server in charge of delivering the app should not be the one running the queue.
Therefore I spin up another instance of the same docker image with the sole purpose of running artisan queue:work.
Laravel queues provide a unified API across a variety of different queue backends, such as Beanstalk, Amazon SQS, Redis, or even a relational database. Queues allow you to defer the processing of a time consuming task, such as sending an email, until a later time.
Laravel Sail's docker-compose.yml file defines a variety of Docker containers that work together to help you build Laravel applications. Each of these containers is an entry within the services configuration of your docker-compose.yml file.
Laradock is a full PHP development environment for Docker. It supports a variety of common services, all pre-configured to provide a ready PHP development environment.
Laravel Queues Queue Driver Configuration A queue driver is the handler for managing how to run a queued job, identifying whether the jobs succeeded or failed, and trying the job again if configured to do so.
If you need graceful shutdown for queue, you can follow this.
This is taken from @Paul Redmond's article at Laravel News and extending his docker-entrypoint file so suite my need. After a lot of testing for graceful shutdown I finally was able to do.
First thing in docker-compose.yml file set stop_signal: SIGTERM
for your queue service.
queue:
image: laravel-www
container_name: laravel-queue
stop_signal: SIGTERM
depends_on:
- app
volumes:
- .:/var/www/html
...
Next in the entrypoint.sh file, the main thing is to run the queue:work using the exec
command.
#!/usr/bin/env bash
set -e
# Run our defined exec if args empty
if [ -z "$1" ]; then
role=${CONTAINER_ROLE:-app}
env=${APP_ENV:-production}
if [ "$env" != "local" ]; then
echo "Caching configuration..."
(cd /var/www/html && php artisan cache:clear && php artisan config:clear && php artisan route:clear && php artisan view:clear)
(cd /var/www/html && php artisan config:cache && php artisan event:cache && php artisan route:cache && php artisan view:cache)
fi
if [ "$role" = "app" ]; then
echo "Running PHP-FPM..."
exec php-fpm
elif [ "$role" = "queue" ]; then
echo "Running the queue..."
exec php /var/www/html/artisan queue:work -vv --no-interaction --tries=3 --sleep=5 --timeout=300 --delay=10
elif [ "$role" = "cron" ]; then
echo "Running the cron..."
while [ true ]
do
exec php /var/www/html/artisan schedule:run -vv --no-interaction
sleep 60
done
else
echo "Could not match the container role \"$role\""
exit 1
fi
else
exec "$@"
fi
Your are done. Next time you stop queue service, it will stop gracefully and won't wait 10 seconds for SIGKILL
. I think it has to do with the PID 1
thing.
The queue:work command runs in the foreground, so you should run it that way so the container doesn't exit immediately.
Since the application code in Laravel is the same for running a container as a web application, queue, or scheduler I build one image that I can use in these contexts. I use a bash start script with an environment variable to define a container role, and this is what I run for a queue worker container:
#!/bin/bash
# Defaults to an app server
role=${CONTAINER_ROLE:-app}
if [ "$role" = "queue" ]; then
# Run queue
php artisan queue:work --verbose --tries=3 --timeout=90
elif [ "$role" = "app" ]; then
# Run the web application
/usr/bin/caddy --agree=true --conf=/etc/Caddyfile
elif [ "$role" = "scheduler" ]; then
while [ true ]
do
php artisan schedule:run --verbose --no-interaction &
sleep 60
done
else
echo "Could not match the container role...."
exit 1
fi
Also note the infinite while loop and sleep combo to keep the scheduler role running and running the schedule:run command in the background in case the scheduler runs overlap (since they need to run every minute regardless of if the last one finished).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With