Manoj Kalluri
Manoj Kalluri

Reputation: 1464

How to run a cron job inside a docker container

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.

Upvotes: 66

Views: 105939

Answers (5)

x-yuri
x-yuri

Reputation: 18823

You don't say much about what you did, but one way would be to make use of dcron and Alpine Linux:

docker-compose.yml:

services:
  dcron:
    build: .
    command: crond -fl info
    init: yes

Dockerfile:

FROM alpine:3.17
RUN set -x \
    && apk add --no-cache dcron shadow \
    && useradd -m app
COPY crontab /etc/crontabs/app

crontab:

* * * * * date >/dev/null 2>&1

(You can find a bit more information in my gist.)

Here I make it run tasks under non-root, since you shouldn't give more privileges than is needed (principle of least privilege), even inside a docker container.

The downside of this solution is that you can't see tasks' output in docker logs. Which is why I suggest you to give a try to a docker-friendly cron implementation, e.g. supercronic:

docker-compose.yml:

services:
  supercronic:
    build: .
    command: supercronic crontab

Dockerfile:

FROM alpine:3.17
RUN set -x \
    && apk add --no-cache supercronic shadow \
    && useradd -m app
USER app
COPY crontab .

crontab:

* * * * * date

You can also check out my gist about supercronic, and my other answer, which provides examples of using other cron implementations.

Upvotes: 3

Jesus Iniesta
Jesus Iniesta

Reputation: 12469

@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

...

Upvotes: 11

Janis Karklins
Janis Karklins

Reputation: 533

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']

Upvotes: 0

Jarek Przygódzki
Jarek Przygódzki

Reputation: 4402

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.

Upvotes: 15

Ken Cochrane
Ken Cochrane

Reputation: 77315

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.

Upvotes: 171

Related Questions