Minimal Dockerized Cron Template
While Docker is mainly used to containerize stateless applications, there might be cases where you need scheduled tasks inside your container. For example, quite often I use it for small automated tasks, such as site updates, database cleanups, and so on. The main reason I prefer this approach is that it becomes really easy to move it to another hosting provider whenever you find a cheaper one.
Implementation notes
Dockerfile
Base Image and Updates:
FROM ruby:3.1 RUN apt-get update RUN apt-get install -y cron
Since for my tasks I use Ruby, I use here Ruby Docker image where I install the Cron daemon in a separate step.
Setting Up the Working Directory and Files:
WORKDIR /app COPY run.sh /app/ COPY run-cron /app/run-cron
This sets
/app
as the working directory. The filesrun.sh
andrun-cron
are copied into/app
.run.sh
contains the script to be executed by Cron, andrun-cron
is the crontab file which schedules whenrun.sh
will be run.Configuring Cron:
RUN cp /app/run-cron /etc/cron.d/run-cron RUN chmod 0644 /etc/cron.d/run-cron RUN crontab /etc/cron.d/run-cron
The Cron configuration file is moved to
/etc/cron.d
and set with the correct permissions. Thecrontab
command adds the schedule fromrun-cron
into the Crontab.Logging Setup:
RUN touch /var/log/cron.log CMD cron && tail -f /var/log/cron.log
An empty log file is created and the
CMD
command starts the Cron daemon along with tailing the log file. This enables the logs to be streamed to the Docker container logs, which can be very useful for debugging.
Logs redirections
Debugging failing cron jobs could be a burden, so I redirect the output and errors from the Cron job are sent to the standard output and error streams of the container by doing:
0 0 * * * /app/run.sh > /proc/1/fd/1 2>/proc/1/fd/2
Running
All you left to do is to build an image and run it in detached mode
The Full Template
Dockerfile
FROM ruby:3.1
RUN apt-get update
RUN apt-get install -y cron
WORKDIR /app
COPY run.sh /app/
COPY run-cron /app/run-cron
RUN cp /app/run-cron /etc/cron.d/run-cron
RUN chmod 0644 /etc/cron.d/run-cron
RUN crontab /etc/cron.d/run-cron
RUN touch /var/log/cron.log
CMD cron && tail -f /var/log/cron.log
run-cron
0 0 * * * /app/run.sh > /proc/1/fd/1 2>/proc/1/fd/2
run.sh
echo "Hello cron!"