9

I have made a Docker image, from a Dockerfile, and I want a cronjob executed periodically when a container based on this image is running. My Dockerfile is this (the relevant parts):

FROM l3iggs/archlinux:latest

COPY source /srv/visitor

WORKDIR /srv/visitor

RUN pacman -Syyu --needed --noconfirm \
        && pacman -S --needed --noconfirm make gcc cronie python2 nodejs phantomjs \
        && printf "*/2 * * * *       node /srv/visitor/visitor.js \n" >> cronJobs \
        && crontab cronJobs \
        && rm cronJobs \
        && npm install -g node-gyp \
        && PYTHON=/usr/sbin/python2 && export PYTHON \
        && npm install

EXPOSE 80

CMD ["/bin/sh", "-c"]

After creation of the image I run a container and verify that indeed the cronjob has been added:

crontab -l

*/2 * * * *     node /srv/visitor/visitor.js

Now, the problem is that the cronjob is never executed. I have, of course, tested that "node /srv/visitor/visitor.js" executes properly when run manually from the console.

Any ideas?

dlyk1988
  • 415
  • 1
  • 7
  • 22
  • 3
    cron requires a daemon. half the process is creating the job, which resides in the cron's file storage. The other half to cron is executing jobs. you might look at: http://stackoverflow.com/questions/20545554/how-do-i-start-cron-on-docker-ubuntu-base. If you want the host's cron daemon to do your cronwork you would probably need to mount the hosts cron directory when you start the container? That doesn't sound good though! – Greg Apr 01 '15 at 12:59
  • Greg, why don't you add that as answer? I was about to say the same. Also note the Phusion image comes with cron running. – Adrian Mouat Apr 01 '15 at 13:02
  • @Greg I can now understand what you are saying. The thing is, I do not want to either mount the host's cron directory, or run systemd inside the container (as per some other suggestions). I feel like both of these methods would unnecessarily "pollute" an otherwise clean system. What are my alternatives? Can I run cronie without systemd? Or, is there an alternative? – dlyk1988 Apr 01 '15 at 14:02
  • @dsljanus what's wrong the suggestions in the link Greg gave you? If you want to run cron and another process you will have to either take care of that in a entrypoint/cmd script or use systemd/supervisor/runit etc. – Adrian Mouat Apr 01 '15 at 16:54
  • @Adrian I just felt like it was already answered in the SO reference I provided, so I didn't answer again. I think your reference to Phusion is interesting for the OP. Perhaps you can provide the new Dockerfile (with the FROM changed) as the answer? That would be new information. – Greg Apr 01 '15 at 17:48
  • @AdrianMouat How could I possibly run cronie from the "CMD" command inside the Dockerfile. It would be very interesting to start the daemon without systemd. – dlyk1988 Apr 01 '15 at 19:18
  • 1
    @dsljanus Why couldn't you? The only problem will be if you can't get it to stop forking to the background. Does `CMD cron -f`work? – Adrian Mouat Apr 01 '15 at 20:28

3 Answers3

8

One option is to use the host's crontab in the following way:

0 5 * * * docker exec mysql mysqldump --databases myDatabase -u myUsername -pmyPassword > /backups/myDatabase.sql

The above will periodically take a daily backup of a MySQL database.

If you need to chain complicated commands you can also use this format:

0 5 * * * docker exec mysql sh -c 'mkdir -p /backups/`date +\%d` && for DB in myDB1 myDB2 myDB3; do mysqldump --databases $DB -u myUser -pmyPassword > /backups/`date +\%d`/$DB.sql; done'

The above takes a 30 day rolling backup of multiple databases and does a bash for loop in a single line rather than writing and calling a shell script to do the same. So it's pretty flexible.

Or you could also put complicated scripts inside the docker container and run them like so:

0 5 * * * docker exec mysql /dailyCron.sh
snez
  • 2,400
  • 23
  • 20
6

It's a little tricky to answer this definitively, as I don't have time to test, but you have various options open to you:

  • You could use the Phusion base image, which comes with an init system and cron installed. It is based on Ubuntu and is comparatively heavyweight (at least compared to archlinux) https://registry.hub.docker.com/u/phusion/baseimage/

  • If you're happy to have everything started from cron jobs, you could just start cron from your CMD and keep it in the foreground (cron -f).

  • You can use lightweight process manager to start cron and whatever other processes you need (Phusion use runit, Docker seem to recommend supervisor).

  • You could write your own CMD or ENTRYPOINT script that starts cron and your process. The only issue with this is that you will need to be careful to handle signals properly or you may end up with zombie processes.

In your case, if your just playing around, I'd go with the last option, if it's anything more serious, I'd go with a process manager.

Adrian Mouat
  • 44,585
  • 16
  • 110
  • 102
  • First things first, thank you for your thorough answer. I'm inclined to go with the second option, running cron with the CMD command, since all I want to do is run a single command every 2 minutes ad infinitum. Thing is, Arch has no "cron" since cronie is an aftermarket package. Also, if this is oveecome, can I run cron in the background? So I can attach to the container should I ever want to. – dlyk1988 Apr 01 '15 at 20:46
  • I don't know anything about cronie, but I expect it will work just the same. You can still get into the container with `docker exec -it CONTAINER /bin/bash`, so that's not a problem. – Adrian Mouat Apr 01 '15 at 21:43
  • Inside the running container, crond is running, and verified by "ps -aux | grep cron". Of course it was stated manually. Thing is, still no cronjobs are being executed. – dlyk1988 Apr 02 '15 at 09:46
  • Cool, you're close then. I suspect it's now just a cron config question; perhaps it isn't picking up your config file or something. – Adrian Mouat Apr 02 '15 at 10:57
  • The crontab file has my jobs set up correctly. If the daemon is also running, what else may need to be configured? – dlyk1988 Apr 02 '15 at 11:27
  • I'm afraid I can't help you there. I don't think it's a Docker issue. – Adrian Mouat Apr 02 '15 at 11:41
  • I have the same last problem @dsljanus. Did you solve it? – Guillaume Cisco Oct 03 '16 at 10:43
3

If you're running your Docker container with --net=host, see this thread: https://github.com/docker/docker/issues/5899

I had the same issue, and my cron tasks started running when I included --pid=host in the docker run command line arguments.

Fazan
  • 31
  • 1