I really like the way we configure crons in our Yii application – any developer can setup a cron with just a code comment. As example, look at this function header comment that will result in the function being triggered automatically every 3 minutes:
* Requeue a task if undelivered after deadline has passed
* @cron *\3 * * * *
* @cron-tags live staging
public function actionRequeue()
The magic that parses these comments and triggers the functions is a Yii extension called phpdoc-crontab which itself needs to be run as a cron every minute. We run the phpdoc-crontab cron from a docker container as follows:
* * * * * docker exec apprunner php /var/www/ourapp/yiic cron run live
Notice that the
docker exec command is not using the
-t flag (i.e.
--tty=false a.k.a. docker does not allocate a pseudo-TTY for us). This is critical. If the
-t flag is used, it will not work. Docker (at least in v1.5) will kill any child processes once the
docker exec command finishes. This was a gotcha for me that took a few hours to discover. The following is a verification:
Start a busybox container in the background:
docker run -d --name busybox busybox /bin/sh -c "while true; do echo Hello world; sleep 1; done"
Run a command in busybox that forks a child process into the background:
docker exec -t busybox sh -c "(echo start);(sleep 60 &);(echo end)"
Notice that it returns immediately and Docker killed the “sleep 60” child process when the exec exited. This can be seen by doing a ps straight after:
docker exec busybox ps aux
Now try again, but without the
-t flag, this time notice how Docker waits for the child process to finish before returning:
docker exec busybox sh -c "(echo start);(sleep 20 &);(echo end)"
So, the morale of the story, if your
docker exec command forks background processes, be sure to avoid the