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
/appas the working directory. The filesrun.shandrun-cronare copied into/app.run.shcontains the script to be executed by Cron, andrun-cronis the crontab file which schedules whenrun.shwill 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.dand set with the correct permissions. Thecrontabcommand adds the schedule fromrun-croninto 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
CMDcommand 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
Once cron container is started, how to know if cron job is working? For this purpose 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
After that you can monito the container logs in such way:
docker logs -f <container name>
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!"