Why the -t docker flag should not be used for background processes

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 -t flag.

Tags > , , ,

No Comment

Post A Comment