55

I tried to run a cron job inside a docker container but nothing works for me.
My container has only cron.daily and cron.weekly files.
crontab,cron.d,cron.hourly are absent in my container.
crontab -e is also not working.
My container runs with /bin/bash.

Jonas
  • 109,920
  • 93
  • 295
  • 369
Manoj Kalluri
  • 1,304
  • 2
  • 14
  • 25

4 Answers4

148

Here is how I run one of my cron containers.

Dockerfile:

FROM alpine:3.3

ADD crontab.txt /crontab.txt
ADD script.sh /script.sh
COPY entry.sh /entry.sh
RUN chmod 755 /script.sh /entry.sh
RUN /usr/bin/crontab /crontab.txt

CMD ["/entry.sh"]

crontab.txt

*/30 * * * * /script.sh >> /var/log/script.log

entry.sh

#!/bin/sh

# start cron
/usr/sbin/crond -f -l 8

script.sh

#!/bin/sh

# code goes here.
echo "This is a script, run by cron!"

Build like so

docker build -t mycron .

Run like so

docker run -d mycron

Add your own scripts and edit the crontab.txt and just build the image and run. Since it is based on alpine, the image is super small.

Ken Cochrane
  • 72,249
  • 9
  • 48
  • 58
  • 1
    This is great. One problem I'm having is that after docker run ... I'm not able to stop the container running using ctrl-c? Even after I close the terminal, when I do docker ps I can see that the container is still up. Does anyone have the same problem? – ztech Apr 23 '18 at 18:19
  • @ztech did you try doing "docker stop "? – Ken Cochrane Apr 24 '18 at 18:31
  • Yeah I had to use docker kill . In retrospect it is most likely not a docker issue and some side effect of the scripts I was running using the crontab. I made a little different configuration of my scripts now and think this is a non-issue. – ztech Apr 24 '18 at 19:38
  • 3
    Please add `RUN apk add --update apk-cron && rm -rf /var/cache/apk/*` to the answer for a full example. There are so many ways to add cron to alpine listed out there, and this one is the one that works with your example. – Fmstrat May 29 '18 at 15:05
  • 3
    Hi, why there are 2 ADD and 1 COPY?, base on what I read seem like 3 COPY or 3 ADD would work fine(in this case). am I right? – NamNamNam Jan 26 '19 at 05:53
  • It's good to know that if you're just adding files to an image and changing entrypoint/command, it can all be done with configuration at container creation without building a new image. – Phil Jun 17 '19 at 07:45
  • It'd be nice if you didn't have to create a full container just for a simple cronjob. What would be a good way to *add a cronjob to a pre-existing container* instead of creating a new/separate container? – code_dredd Jun 19 '19 at 19:34
  • 4
    `crond -f -l 8`, What does the 8 mean? According to man, the log level is with a capital `L`. – jcarlosweb Mar 19 '21 at 11:10
  • @jcarlisweb different versions of CRON have different flags. Some use upper case L for log file and lower case l for log level. See http://man.gnu.org.ua/manpage/?8+crond as an example. Pick what works for your version of CRON – Ken Cochrane Mar 20 '21 at 12:16
  • 1
    I don't see crond running in the container as default. I had to exec and run crond which actually triggered the cron job. Is there something I'm missing here ? – Avi Apr 14 '21 at 23:12
11

crond works well with tiny on Alpine

RUN apk add --no-cache tini

ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/sbin/crond", "-f"]

but should not be run as container main process (PID 1) because of zombie reaping problem and issues with signal handling. See this Docker PR and this blog post for details.

Jarek Przygódzki
  • 4,114
  • 2
  • 29
  • 40
5

@ken-cochrane's solution is probably the best, however, there is also a way to do it without needing to create extra files.

To do it without extra files:

The way to go is to set the cron within your entrypoint.sh file.

Dockerfile


...

# Your Dockerfile above


COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh


echo "* * * * * echo 'I love running my crons'" >> /etc/crontabs/root
crond -l 2 -f > /dev/stdout 2> /dev/stderr &

# You can put the rest of your entrypoint.sh below this line

...

JesusIniesta
  • 7,548
  • 1
  • 26
  • 20
  • If you are using alpine linux without bash, don´t forget to add the following to the beggining of the sh file: `#!/bin/ash` – Daniel Miranda May 08 '22 at 04:15
-1

Here is good explanation of cron problems inside docker container:

Docker file example:

FROM alpine

# Copy script which should be run
COPY ./myawesomescript /usr/local/bin/myawesomescript
# Run the cron every minute
RUN echo '*  *  *  *  *    /usr/local/bin/myawesomescript' > /etc/crontabs/root

CMD ['crond', '-l 2', '-f']
Janis Karklins
  • 425
  • 1
  • 6
  • 17
  • This approach doesn't work, as far as I'm concerned. I've tried a few variants too, and it seems like in the final container, changes made to `/etc/crontabs/root` aren't there. – JesusIniesta Aug 01 '21 at 17:35