Run a cron job with Docker

| 32 Comments | 2 minutes read

ContainersAt ekito, we adopted Docker as lightweight virtualization solution to deploy our internal servers, as well as deliver “ready to run” applications to our customers.

Bert has already published an excellent article on Docker, one year ago. Since then, we continued to experiment on this topic and I would like to present a very simple (but not trivial) use case:
run a cron job in a docker container.

The source code is available on github.

Install docker

Depending on your platform, you can find the complete documentation on the docker website.

The cron job

We will create a cron job that will display “Hello world”, every minute, in the console

Let’s create a new file called “crontab” to describe our job.

* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.

This job will echo “Hello world”, every minutes, and redirect the output in the file /var/log/cron.log

Important remarks:

  • a blank line is required at the end of this file!
  • the job is run by the “root” user as it is the only user that will exist in the container

The docker image

The following DockerFile describes all the steps to build your image

FROM ubuntu:latest
MAINTAINER docker@ekito.fr
 
# Add crontab file in the cron directory
ADD crontab /etc/cron.d/hello-cron
 
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
 
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
 
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

Then you can build the image with

sudo docker build --rm -t ekito/cron-example .

And run it:

sudo docker run -t -i ekito/cron-example

Be patient, wait for 2 minutes and your commandline should display:

Hello world
Hello world

Now you can create you own script to backup you data, check your system status, or whatever you want !

Julien Boulay Author: Julien Boulay

Eclectic developer & architect
Activist for usability, performance and interoperability of systems.

My favorite quote : "The best feature is the one we don't need to develop !"

My hashtags : #windchill #java #talend #nodejs #angularjs #oss #docker

Like it?  Share  it!

Share Button

32 Comments

  1. Pingback: Run cron in centOS as user process, not daemon | DL-UAT

  2. Pingback: Run cron in centOS as user process, not daemon | You need? We have! Everything

  3. To use this in production, you probably want cron to run in the forground like this:

    CMD [“cron”, “-f”]

  4. Um… this doesn’t work. I waited for 5 minutes and nothing is displayed. How can I debug this?

    • Julien Boulay

      Hi Austin,

      Thanks for your interest on this post.

      To debug this, you can enter the container : while the docker container is running in one terminal, open a new terminal and type :
      `sudo docker exec -it your_container_name /bin/bash`

      Then you should see something like :
      `root@677490a5df26:/#`

      You are now connected inside the container. You can edit the cron configuration, restart the service and check the logs.

      Exemple : check if your cron process is running :
      `ps -ef |grep cron`
      There should be one process like
      `root 1 0 0 20:38 ? 00:00:00 /bin/sh -c cron && tail -f /var/log/cron.log`

      Please give me your feedback if I miss something in this post.

    • try putting

      RUN /usr/bin/crontab /etc/cron.d/hello-cron

  5. Nice article! Thx

  6. Nice article but the use case is quite dummy. Would be much better to have an example of cron job executed for a different container than cron container.

    • Julien Boulay

      Hi jangorecki,

      Thanks for your comment. You’re right, it is a very simple use case. But usually, it is recommended to execute only one process by container. We could imagine run a cron in one container, that will access a shared volume…
      The idea was to keep the article as simple as possible to illustrate the usage and debugging of a cron.

  7. Hi,

    I try to get it working on a centos 7 httpd container. The daemon crond doesn’t start. Is someone have successfully startup cron in a container that already run another daemon (like httpd) ?

    I tried with RUN/CMD crond before the startup CMD for httpd, but it’s not working. I suppose that it is not possible to start multiple daemon in the same container ? if I just try to start the crond daemon without httpd, it works.

  8. Thanks for this, however, you should be aware that cron can’t access any environment variables you pass into the container… making life pretty difficult if you’re running commands for an app that may require stuff.

  9. Nice article!. Thanks. Specially the commented line help me a lot
    # An empty line is required at the end of this file for a valid cron file.

  10. Pingback: 使用Docker Compose管理Docker容器 | 勇气

  11. do you know as run the cron in another’s containers simultaneously? For example, if i have three containers, configure crontab for all. I’m trying, but not work, the cron, only run in one container. I using the next method:

    edit:
    crontab -e

    and put: */2 * * * * export PATH=”/root/driver:$PATH” && cd /root/file && /usr/bin/ruby /root/file/file.rb

    Thanks.

  12. Hi Julien!

    It’s worth noting, that:

    1. It would be better to mount the ‘crontab’ file straight from your project directory, to keep it up to date on every container startup.

    2. You should rather mount a separate volume for logs from the host machine, to keep your logs outside the container OR create fifo file for logs.

    • Julien Boulay

      Hi Dimitri,

      Thank you very much for your remarks. You are right, it would be much better to mount external file systems to control crontab and logs files.
      I will test it and update my post soon with external directories.

  13. I created a similar image but all bases on env vars , no config files to mount.

    let me know what you think

    https://www.vip-consult.solutions/post/better-docker-cron#content

  14. Thank you for this article Julien. Cannot get it to work with a container using python:2.7 image. I see the cron -f process running, and my cron job is in the /etc/cron.d/hello-cron, but I’m getting no cron jobs auto firing after 5 minutes of waiting.

    Any help would be appreciated as I’ve been messing with this for too many hours.

    • Julien Boulay

      Hi Eric,

      Thanks for your comment.
      Don’t you miss to add a blank line to the end of the cron file ?
      What is the OS of your base image ? Ubuntu, CentOS, … ?
      Could you please give me more details about your implementation, or push a sample of the project on a github repo ?

  15. Pingback: Gestione multidominio con Docker - Ajenti-V - Letsencrypt » m4-Web

  16. For those having trouble, I solved issues (below). I assume you’re using “FROM ubuntu:latest” for the current LTS. I suspect some things changed in the base image since the time this was written.

    (Use whatever you want of course, but I strongly suggest deferring experimentation with non-Ubuntu base… get the basics working first)

    Problem: missing ‘crontab’ file
    “`Step 6/7 : RUN /usr/bin/crontab /etc/cron.d/hello-cron
    —> Running in 19b11a035f00
    /bin/sh: 1: /usr/bin/crontab: not found“`

    Solution: add:
    “`RUN apt-get update && apt-get install -y cron“`

    Problem:
    “`# /bin/sh: 1: root: not found“`

    Solution: remove ‘root’ from column 6 of the cron file. The command will be implicitly run as root and column 6 should contain the command.

    Problem: nothing output
    Also add:
    RUN /usr/bin/crontab /etc/cron.d/hello-cron
    (leave in the CMD cron && tail -f /var/log/cron.log)

    Other suggestions:
    If you’re having trouble differentiating images and instances because you are new, edit the cron file to say “Hello world2” etc., because nothing’s worse than making changes and not seeing them work as expected because the wrong thing is executed.. 🙂

What do  You  think? Write a comment!

Leave a Reply

Required fields are marked *.


CommentLuv badge