Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jimmy.puckett's avatar

Run the scheduler in a docker image?

We are trying to decide the best way to run the scheduler in a docker container. Given that the php /path/to/artisan schedule:run >> /dev/null 2>&1 command runs & then exits, you cannot let it be the CMD for the Docker file unless you launch a new container for each minute to run the scheduler. We have 3 options that are considering...

  1. Have a shell script for the CMD that is in a loop that calls php /path/to/artisan schedule:run >> /dev/null 2>&1 & then sleeps for the balance of a minute

  2. Add a new artisan command like schedule:loop that does what #1 above does but in php. Then use the artisan command as the CMD for the docker file

  3. Have the docker scheduler launch a new container every minute with an image that has the php /path/to/artisan schedule:run >> /dev/null 2>&1 as the CMD

For any of you that are running laravel in docker, how are you solving this issue?

0 likes
16 replies
willvincent's avatar

you could configure a cronjob.. ssh into the docker machine and run crontab -e to edit the crontab file. Most likely that'll open with vi..

jimmy.puckett's avatar

@willvincent , thanks, but this does not fell very docker in practice. As each container is supposed to have a single purpose. You don't really run other services/jobs. Additionally, there is not ssh. You could attach to the running instance, but they replace themselves to allow growth & updates.

Thanks again for taking the time to respond.

willvincent's avatar

cron barely qualifies as another job being such a tiny daemon that might as well be just part of the linux kernel.

patant's avatar

I did go with option 3. No problem running a container every minute just make sure you remove it after each run (--rm). One problem is that schedule:run forks new php processes. And before those processes has been executed the schedule:run process ends and container exits. Solved it by running 'php artisan schedule:run >> /dev/null 2>&1 && while pgrep php > /dev/null; do sleep 1; done'

1 like
willvincent's avatar

I still say this would be much easier and, in my opinion better, to do with a regular cron task. If the container for the site is active, cron will fire as expected. no extra containers need to be loaded/etc.. The argument that this "isn't the docker way" is .. frankly, bunk.

patant's avatar

I have access to a scheduler and I don't need to create another container for cron. And no need to have a cron instance running all the time consuming resources of my docker cluster.

pmall's avatar

Add a cronjob and run the docker with -d. No problem with this regarding docker philosophy.

jimmy.puckett's avatar

@pmall, Why have a dormant container running opposed to letting the scheduler just run an image that directly runs the job. Also, how do you cleanly replace the container when doing upgrades as the scheduler would not know if the cronjob is running whereas by updating the image, on the next scheduled execution of the image, it would pick up the update.

pmall's avatar

Why have a dormant container running opposed to letting the scheduler just run an image that directly runs the job.

@jimmy.puckett So your server will have a cronjob running a docker container periodically? So everytime you deploy your application on a new server, you need to configure the cronjob. The point of using docker is to not have to configure anything other than orchestrating containers.

For the updates, if you use docker-compose it handles updates nicely, just run docker-compose up -d again and it will rebuild and restart only updated images.

Dont overthink this, having a container running a cronjob is not a problem, plenty of images do so. It still has only one purpose : running a script priodically. It is not like your container contains both a database engine and a webserver. If this really bother you you can make an artisan command running the scheduler periodically and call this command.

2 likes
paulredmond's avatar

@jimmy.puckett try something like this in an entrypoint.sh file:

#!/bin/bash

# Run scheduler
while [ true ]
do
  php artisan schedule:run --verbose --no-interaction
  sleep 60
done

The Dockerfile's CMD (along with an example of copying the file into the container and making the file executable):

#...Dockerfile stuff...

COPY docker/scheduler/entrypoint.sh /opt/bin/entrypoint.sh
RUN chmod +x /opt/bin/entrypoint.sh

CMD ["/opt/bin/entrypoint.sh"]

The entrypoint keeps an infinite while loop running in the foreground which mimics a cron by sleeping every 60 seconds before running the scheduler again. Cheers!

As another example, here I used one docker build that can run as a queue or an app server (I am using Caddy, but swap for apache or nginx if you want) based on the environment role. I didin't use the scheduler in this way because my scheduler has other dependencies that made me want to separate the image, but the scheduler could be another role if you have a fairly normal app use case.

The image is identical other than needing to run a server vs an artisan command:

#!/bin/bash

# Defaults to an app server
role=${CONTAINER_ROLE:-app}

echo "Container role: $role"

if [ "$role" = "queue" ]; then
    # Run queue
    while [ true ]
    do
      php artisan queue:work --verbose --tries=3 --timeout=90
    done
elif [ "$role" = "app" ]; then
    /usr/bin/caddy --conf /etc/Caddyfile
else
    echo "Could not match the container role...."
    exit 1
fi
7 likes
neto-braghetto's avatar

why not set up a cron in your host machine with this?

* * * * * docker exec -i [CONTAINER_NAME] php /var/www/[PROJECT_FOLDER]/artisan schedule:run >> /dev/null 2>&1
4 likes
xmaop's avatar

Hi, the cron service inside container is not running.

Try:

sudo docker -ti containerid bash
service cron start
exit

Use supervisor, to run every time that restart server or container.

Please or to participate in this conversation.