In this tutorial we’ll be setting up Cron jobs in Docker and discuss how to avoid a common pitfall.

Let’s Code It!

We’ll build a cron job that runs while other services on docker are running. This is particularly useful if we want to backup our databases.

Setting things up

Directory structure.

/docker-cron
    /node-app
    /cron-app
    docker-compose.yml

Create a docker-cron root directory.

Container #1: Node

To start we’ll setup a node image that will act as a service that’s supposed to run while the cron job is running.

Generate a blank node app in docker-cron:

express node-app

Create a Dockerfile in the node-app directory:

FROM node

MAINTAINER Steve Jobs

WORKDIR /src

COPY . /src

RUN npm install

EXPOSE 3000

ENTRYPOINT ["npm", "start"]


Common Pitfall

Running cron in the same container as a service.

The Docker ubuntu image by default doesn’t run cron at runtime because it’s intended to run only one process at a time. Below is improperly attempting to run two processes simultaneously, something Docker doesn’t support:

CMD node app.js && cron -f

The trick is splitting cron into its own separate container.



Container #2: Cron

We’ll setup an ubuntu image that will run our cron job in a seperate container. This image doesn’t come with cron by default, so we’ll need to install it and do a general update. Create a cron-app directory in the docker-cron project folder.

Create mycron in cron-app that specifies your cron:

* * * * * /cron/do.sh >>  /cron/cron.log 2>&1

Make sure you have a blank line at the end of mycron

This cron will run every minute.

Create do.sh in cron-app that specifies what your cron does:

#!/bin/sh
echo "Cron is called."

Create a Dockerfile in the cron-app directory with the following contents:

FROM ubuntu

MAINTAINER Steve Jobs

WORKDIR /cron
ADD mycron .
ADD do.sh .

RUN apt-get update
RUN apt-get install cron

RUN touch /cron/cron.log

RUN chmod +x do.sh
RUN chmod 0600 mycron

RUN crontab -u root mycron

ENTRYPOINT ["cron", "-f"]


Docker Compose

Now we’ll bring the two images together with Docker Compose.

Create a docker-compose.yml file in the root docker-cron directory with the following contents:

version: '2'
services:
    node:
        build: ./node-app
        ports:
        - "3000:3000"
    cron:
        build: ./cron-app

View the Code

All the code for this tutorial can be viewed on github: https://github.com/gdayton/coderbro_code/tree/master/docker-cron.