Notes, Thoughts & Ideas

Thoughts, stories and ideas.

Cron with a separate Docker container

Lately I was required to clean redundant Elasticsearch indices. Every midnight. Easy thing for a cron job, right? The main thing was, that the whole infrastructure is built around Docker containers and there is no server on which it is possible to run cron.

After googling for a while I haven't found nice and short image for this and therefore start to creating my own.

I wanted to have: the smallest image possible; robust solution - the simplest bash scripts; configurability.

The Alpine image is the smallest available. The small issue I've instantly found: the date util from it doesn't support proper -d formatting:

date: invalid date '2 days ago'

This can be fixed with installing the coreutils. Thus my Dockerfile look like this:

FROM alpine:latest
MAINTAINER "Andrew Prokhorenkov"
USER root
RUN apk update && apk add --no-cache curl coreutils
COPY crontab /etc/crontabs/root
COPY /tmp/
RUN chmod -v +x /
RUN mkdir -p /var/log/cron && touch /var/log/cron/cron.log
CMD ["/"]

The command is a separate script in which I put the environment variables into script and run the crond with logging.

env | egrep '^ES_' | cat - /tmp/ > /
crond -L /var/log/cron/cron.log "$@" && tail -f /var/log/cron/cron.log

Easy, huh? Easy. :)

The actual script in cleaning the indices is also simple:

for day in $(seq $KEEP $(($KEEP + 7)))
   IDX_DATE=$(date -d "$day days ago" +%Y-%m-%d)
   curl -s -XDELETE -u $ES_USER:$ES_PASS https://$ES_URL/$ES_INDEX-$IDX_DATE || true

Where all the variables ($KEEP, $ES_USER, $ES_PASS, $ES_URL, $ES_INDEX) is being passed to container via environment file in Docker Compose:


With the final touch of crontab it is finished.

0 0 * * * sh / >> /var/log/cron/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.

Now you only need to build it and use in docker-compose.yml or standalone run.

I hope this will help someone to run the cron in Docker container.