Handling cron jobs in docker?

How are people generally handling cron jobs with docker? The most common case I’ve seen is there will be a sidekick image running just crond and the code base, however when using cronie I’m not able to read in any environmental variables that are passed in on the docker command line.

Specifically I’ll do this:

  • How to retrieve running version from ElasticBeanstalk app instance?
  • Docker for Windows error: “Hardware assisted virtualization and data execution protection must be enabled in the BIOS”
  • Difference between Docker and OpenVZ
  • How to config spring cloud oauth2 in docker container
  • (django) (docker) Django webserver wont start
  • docker cp doesn't work for this mysql container
  • docker run -d --name cron -e VAR1=val1 -e VAR2=val2 cron_image start
    

    Inside the image we’ll have this:

    [root@dae7207bf10e /]# yum info cronie
    Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
     * base: mirror.ash.fastserv.com
     * epel: mirror.cs.pitt.edu
     * extras: mirror.vcu.edu
     * updates: mirror.us.leaseweb.net
    Installed Packages
    Name        : cronie
    Arch        : x86_64
    Version     : 1.4.11
    Release     : 13.el7
    Size        : 211 k
    Repo        : installed
    Summary     : Cron daemon for executing programs at set times
    URL         : https://fedorahosted.org/cronie
    License     : MIT and BSD and ISC and GPLv2+
    Description : Cronie contains the standard UNIX daemon crond that runs specified programs at
                : scheduled times and related tools. It is a fork of the original vixie-cron and
                : has security and configuration enhancements like the ability to use pam and
                : SELinux.
    
    [root@dae7207bf10e /]# cat /usr/local/bin/start
    #!/bin/bash
    /usr/bin/env > /var/tmp/docker_env
    /usr/sbin/crond -n
    

    And my crontabs will look like this:

    SHELL=/bin/bash
    5 16 * * * source /var/tmp/docker_env; /usr/local/bin/randomchallenge &> /var/log/randomchallenge.log
    

    Originally I didn’t have the source bits at all and tried to use the variables directly however it doesn’t look like cronie presents them to called jobs (which does make sense in the vast majority of use cases). I’ve tried pulling in this env file a variety of ways without luck, my program can never read the variables. Even wrapping the whole thing in a shell script that pulls in env doesn’t do the job.

    How are people handling this kind of thing? Hard coding values is not an option. I suppose I could make the start script generate the crontab on the fly but that seems really ugly.

  • Capture output from attached docker container
  • Port forwarding in Jelastic with Docker
  • ehcache not working in Tomcat Docker image
  • How to run maven test with mysql running in docker
  • Spring Boot can't read application.properties in Docker
  • Puppet-Docker Service Error undefined method '[]' for nil:NilClass
  • 2 Solutions collect form web for “Handling cron jobs in docker?”

    Sourcing the env file does not work, I’m not sure why (originally I was chmod +xing the env file, I removed it for this answer so it isn’t that). I ended up finding this wonky env kludge to do it. env can set variables from stdin so we’re just catting our env file, sending it to env, and then using that environment for our actual job.

    [root@b7886c463928 /]# cat /usr/local/bin/start
    #!/bin/bash
    env > /var/tmp/docker_env
    /usr/sbin/crond -n
    [root@b7886c463928 /]# crontab -l
    */1 * * * * env - `cat /var/tmp/docker_env` env > /tmp/cron.check
    

    You’ll need to add this bit before every job

    env - `cat /var/tmp/docker_env`
    

    I’m going to write a lightweight crond clone that can handle standard job formats but passes the environment along and outputs to stdout.

    Cron in docker world (due to whatever reasons) seem to have received lesser love compared to other facilities in a standard Linux environment. I found it not very obvious how to do it correctly.

    Here is my take on the problem and a solution for it. Have a look at docker-vixie-cron and its docker image redmatter/cron to see if it helps your scenario. It did take a bit of trial and error to arrive at the current solution, but please feel free to air your thoughts.

    It is quite different to what you have done with cronie; here is how. In your project you have to add the Dockerfile that has the below lines and a crontab.txt with your cron definition.

    Dockerfile

    FROM redmatter/cron
    
    ADD randomchallenge /usr/local/bin/
    

    crontab.txt

    */1 * * * * /usr/local/bin/randomchallenge >>/var/log/randomchallenge.log 2>&1
    

    If you want to use a different user to root (say because you have another container sharing the cron container), then you can additionally define RUN_USER=another.user and then add the user using a built-in script called cron-user add; as in the below version of Dockerfile.

    Dockerfile with another.user

    FROM redmatter/cron
    
    ENV RUN_USER=another.user
    RUN cron-user add -u another.user
    
    ADD randomchallenge /usr/local/bin/
    

    Run

    In both cases you can run the container using the command as below.

    docker run -d --name cron \
    -e PRESERVE_ENV_VARS="VAR1 VAR2" \
    -e VAR1=val1 -e VAR2=val2 \
    cron_image start
    

    Here it is important to specify PRESERVE_ENV_VARS="VAR1 VAR2" so that VAR1 and VAR2 are preserved for randomchallenge to see.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.