Cronjobs and Docker containers

Intro

In days of virtualization, resource optimization are DevOps developers topic of obsession.

With great Pros would come some Cons…

Some tasks that used to be straightforward for Sysadmins, could be something more elaborate to solve in dockerized environments.

In this post I will show you how to deal with Cron jobs which helps keep our resource optimization as efficient as possible.

Let’s say that we have a Magento project, that needs to run maintenance tasks like reindex database.

The quick response

Most of you would say: just create a container based on Official Linux image (e.g. Ubuntu) and use the crond.

While this is perhaps the easiest option, it is not as effective in terms of resource optimization and development time.  Docker does not allow us to run scripts from one container to another as a security measure which means you have to find ways to expose each and every script you want to be ran by cron.

Solutions

In our example, the crontab can looks like:

*/30 * * * * docker exec mage-container sh -c "/usr/local/bin/php /code/crontab/scripts/test_cron.php >> /var/log/cron.log 2>&1

One step forward

If you are using an orchestration system like Kubernetes, the previous solution is not valid anymore because it generate containers with dynamic names.

Most of you would say “Add a new container based on any cron image and run jobs there”. But, again, the security constraint of Docker does not allow us to run scripts placed in mage-container.

Don’t panic, there’s still a way to execute scripts in other container, we just need to expose them via TPC, then we can invoke them using tools like cURL.

version: '2.1'

services:

cron:
 image: docker-alpine-cron:latest
 container_name: my-cron
 env_file: ./environment.env
 volumes:
   - crontab.data:/etc/cron.d/crontab

As a word of caution, be very careful with security holes or backdoors! You will have to take care of the networking settings to prevent request from sources that don’t come from your cron container.

My alternative

Even though the cron container sounds promising, I choose to add an entrypoint script to my php container, where I installed only cron and syslog instead of full image. With this small tweak I’m able to run scheduled php scripts in the php container.

...
mage-php:
 image: php-fpm
 service: php
 container_name: mage-php
 env_file: ./environment.env
 volumes:
 - ../magento:/code
 entrypoint: "/scripts/php/crons_local.sh"
...

crons_local.sh

#!/bin/sh

# hack to fix wrong size issue
rm -f /var/lib/apt/lists/deb.debian.org_debian_dists_jessie_main_binary-amd64_Packages.gz

apt-get update
apt-get install -y cron rsyslog
# init crontab jobs
cp /code/crontab/mywu.cron /var/spool/cron/crontabs/root
chmod -R 0600 /var/spool/cron/crontabs/root
# enable separated cron log file
sed -i '/cron/s/^#//g' /etc/rsyslog.conf
# starting services
/etc/init.d/rsyslog start
/etc/init.d/cron start

Final thoughts

This is my method of running a resource efficient cron job.  I hope you find it useful.  As with many things in DevOps, it may not be perfect but it gets the job done.  If you have a better approach that has been working for you let me know.

Next Post

Comments

See how we can help

Lets talk!

Stay up to date on the latest technologies

Join our mailing list, we promise not to spam.