Setup a cron in parallel to a one-time job

Create a script file, say run.sh, with the job that is supposed to run periodically.

#!/bin/bash
timestamp=`date +%Y/%m/%d-%H:%M:%S`
echo "System path is $PATH at $timestamp"

Save and exit.

Use Entrypoint instead of CMD

f you have multiple jobs to kick in during docker containerization, use the entrypoint file to run them all.

Entrypoint file is a script file that comes into action when a docker run command is issued. So, all the steps that we want to run can be put in this script file.

For instance, we have 2 jobs to run:

Run once job: echo “Docker container has been started”

Run periodic job: run.sh

Create entrypoint.sh

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

# Setup a cron schedule
echo "* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

Let’s understand the crontab that has been set up in the file

* * * * *: Cron schedule; the job must run every minute. You can update the schedule based on your requirement.

/run.sh: The path to the script file which is to be run periodically

/var/log/cron.log: The filename to save the output of the scheduled cron job.

2>&1: The error logs(if any) also will be redirected to the same output file used above.

Note: Do not forget to add an extra new line, as it makes it a valid cron. Scheduler.txt: the complete cron setup will be redirected to a file.

Using System/User specific environment variables in cron

My actual cron job was expecting most of the arguments as the environment variables passed to the docker run command. But, with bash, I was not able to use any of the environment variables that belongs to the system or the docker container.

Then, this came up as a walkaround to this problem:

  1. Add the following line in the entrypoint.sh
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
  1. Update the cron setup and specify-
SHELL=/bin/bash
BASH_ENV=/container.env

At last, your entrypoint.sh should look like

#!/bin/bash

# Start the run once job.
echo "Docker container has been started"

declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env

# Setup a cron schedule
echo "SHELL=/bin/bash
BASH_ENV=/container.env
* * * * * /run.sh >> /var/log/cron.log 2>&1
# This extra line makes it a valid cron" > scheduler.txt

crontab scheduler.txt
cron -f

Last but not the least: Create a Dockerfile

FROM ubuntu:16.04
MAINTAINER Himanshu Gupta

# Install cron
RUN apt-get update && apt-get install -y cron

# Add files
ADD run.sh /run.sh
ADD entrypoint.sh /entrypoint.sh
 
RUN chmod +x /run.sh /entrypoint.sh

ENTRYPOINT /entrypoint.sh

That’s it. Build and run the Docker image!