Recently, I was looking for an easy solution to run "cron jobs" like TYPO3's scheduler or workers like Symfony's messenger consumer via ddev without adding additional dependencies. I came up with a solution based on the existing supervisord. Here's how to do that.
ddev is an open source tool providing simple, cross-platform, docker based local development setups for web / PHP projects. Find out more at https://ddev.com/ddev-local/
Supervisor is basically a process control system that is able to "watch" processes and restart them on failures, making sure they "just keep on running". See http://supervisord.org/ for more information.
Ddev is already using supervisor in the web image, which you can verify by running
service supervisor status in the ddev container.
How to set up supervisor on ddev
To make sure we do not break the web image, we need to first copy the existing ddev supervisord config in a directory on our local system, in my case I did:
ddev ssh mkdir supervisor_temp cp /etc/supervisor/conf.d/* /var/www/html/supervisor_temp/ exit
Then we create a folder below the
.ddev folder for the configs and move the files from
supervisor_temp to that new folder on the host:
mkdir .ddev/supervisor mv supervisor_temp/* .ddev/supervisor/ rm -Rf supervisor_temp
Next, we need to mount that folder as new supervisor conf folder, by creating a
.ddev/docker-compose.supervisor.yml which adds a volume definition:
version: "3.6" services: web: volumes: - ./supervisor:/etc/supervisor/conf.d
Now we can restart ddev and already have supervisor use a folder which we can populate from the host with our own additional configs.
Example: Symfony messenger:consume worker in ddev
The following example shows how to get the worker for the symfony messenger component configured as a service on supervisor but it can be used for any other worker-like process as well.
With supervisor up and running and having control over the config folder, we only need to create a
.conf file in the
.ddev/supervisor folder to make our service known.
Create a file called
symfony-messenger-consume.conf with the following content:
[program:symfony-consumer] command=/usr/bin/php /var/www/html/bin/console messenger:consume default autorestart=true startretries=10
This will start the consumer on startup automatically as well as restart the consumer if it fails for whatever reason - including up to 10 retries.
Restart ddev after creating the config file and check whether the consumer is running:
ddev ssh ps x | grep consume
Example: "pseudo" cron job for TYPO3 scheduler in ddev
The requirements for running the TYPO3 scheduler are slightly different. Instead of a long-running process we have a process required to run at certain intervals instead. However, we can fake it as long-running process, too, by creating a bash script with an interval in an endless loop.
Caveat: In comparison to a real crontab, this only gives us an easy way to run scripts at a certain interval. Cron itself is a lot more powerful - but in case of the TYPO3 scheduler, all of that power is not necessary.
Create a file called
.ddev/supervisor with the following content (make sure to make it executable with
#!/usr/bin/env bash while true do sleep 60 /var/www/html/vendor/bin/typo3 scheduler:run done
Then add a supervisor conf file in addition
[program:typo3-scheduler] command=/etc/supervisor/conf.d/typo3-scheduler.sh autorestart=true startretries=10
... and restart ddev. The script itself will just keep on running - and because of the sleep-loop it will start the TYPO3 scheduler every minute.
The idea here is taken from the original "Cron Job in ddev" snippet - see https://github.com/drud/ddev-contrib/blob/master/recipes/cronjob/README.md for that (the main difference is that no additional packages are required with supervisor)