Recently I worked on a PHP application that used cron for background processing. Since it took some time to get it right, I’m sharing the solution.
Cron Background
Cron runs commands on a time-based schedule with a minimal environment. The commands are defined in crontab-files. These files use a strict format that includes a newline and require file permission 0644.
Run Cron In A Container
This solution runs Cron as a secondary process in a PHP webserver container. Supervisor controls these processes, and ensures that the container fails as soon as any process fails.
Find all solution sources at GitHub.
The Dockerfile sets the required crontab file permissions and starts Supervisor.
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y &&
apt-get install -y --no-install-recommends cron supervisor
# Configure cron jobs and ensure crontab-file permissions
COPY cron.d /etc/cron.d/
RUN chmod 0644 /etc/cron.d/*
COPY supervisord.conf /etc/supervisor/
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
Supervisor starts Cron with the following configuration.
[program:cron]
command = /bin/bash -c "declare -p | grep -Ev '^declare -[[:alpha:]]*r' > /run/supervisord.env && /usr/sbin/cron -f -L 15"
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes=0
user = root
autostart = true
autorestart = true
Cron runs in foreground mode (cron -f) to allow supervisor to control it.
Supervisors process environment is exported to /run/supervisord.env. This allows Cron jobs to import the Docker/Kubernetes environment variables. The environment is imported by the following Cron job as an example.
* * * * * www-data exec /bin/bash -c ". /run/supervisord.env; /app/script.sh >> /app/cron.log"
Discussion
Background processing is commonplace, but not trivial.. How are executions tracked? How does it scale? How are restarts handled? Cron, for instance, doesn’t help with any of these concerns.
The provided solution is part of an application Replatform. For a future refactor we aim at replacing Cron with Kubernetes Cron or any other modern scheduler. So, please consider modern day scheduler-alternatives for your services.
Try it yourself
Clone the associated GitHub repository and give it a go!
git clone git@github.com:binxio/blog-cron-supervisor-docker.git
docker build -t cron-supervisor-example .
docker run --rm -p 8080:8080 cron-supervisor-example
Read more?
If you need serverless asynchronous processing, read our blog on Google Cloud Tasks and scheduling serverless applications using Cloud Scheduler.
Photo by JESHOOTS.COM on Unsplash