How To Run Container Background Tasks With Cron

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

Photo by JESHOOTS.COM on Unsplash

As a cloud consultant I enjoy taking software engineering practices to the cloud. Continuously improving the customers systems, tools and processes by focusing on integration and quality.
Share this article: Tweet this post / Post on LinkedIn