I would like to run a python cron job inside of a docker container in detached mode. My set-up is below:
My python script is test.py
#!/usr/bin/env python
import datetime
print "Cron job has run at %s" %datetime.datetime.now()
My cron file is my-crontab
* * * * * /test.py > /dev/console
and my Dockerfile is
FROM ubuntu:latest
RUN apt-get update && apt-get install -y software-properties-common python-software-properties && apt-get update
RUN apt-get install -y python cron
ADD my-crontab /
ADD test.py /
RUN chmod a+x test.py
RUN crontab /my-crontab
ENTRYPOINT cron -f
What are the potential problems with this approach? Are there other approaches and what are their pros and cons?
Single Container Method
You may run
crond
within the same container that is doing something closely related using a base image that handles PID 0 well, like phusion/baseimage.Specialized Container Method
May be cleaner would be to have another Container linked to it that just runs
crond
. For example:Dockerfile
crontab
Then run:
Note: In this case it'll run the job as
www-data
. Cannot just mount thecrontab
file as volume because it needs to be owned byroot
with only write access forroot
, elsecrond
will run nothing. Also you'll have to runcrond
asroot
.Don't mix crond and your base image. Prefer to use a native solution for your language (schedule or crython as said by Anton), or decouple it. By decoupling it I mean, keep things separated, so you don't have to maintain an image just to be the fusion between python and crond.
You can use Tasker, a task runner that has cron (a scheduler) support, to solve it, if you want keep things decoupled.
Here an
docker-compose.yml
file, that will run some tasks for youJust run
docker-compose up
, and see it working. Here is the Tasker repo with the full documentation:http://github.com/opsxcq/tasker
Another possibility is to use Crython. Crython allows you to regularly schedule a python function from within a single python script / process. It even understands cron syntax:
Using crython avoids the various headaches of running crond inside a docker container - your job is now a single process that wakes up when it needs to, which fits better into the docker execution model. But it has the downside of putting the scheduling inside your program, which isn't always desirable. Still, it might be handy in some use cases.
We are using below solution. It supports both
docker logs
functionality and ability to hang the cron process in the container on PID 1 (if you usetail -f
workarounds provided above - if cron crashes, docker will not follow restart policy):cron.sh:
Dockerfile:
crontab:
And please don't forget to add the creepy new line in your crontab
Here is a complement on rosksw answer.
There is no need to do some string replacement in the crontab file in order to pass environment variables to the cron jobs.
It is simpler to store the environment variables in a file when running the contrainer, then load them from this file at each cron execution. I found the tip here.
In the dockerfile:
In the crontab file:
Here's an alternative solution.
in
Dockerfile
in
entrypoint.sh