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
.

- 121,568
- 97
- 310
- 388

- 1,384
- 2
- 14
- 27
-
See my answer [here](https://stackoverflow.com/a/75353647/52499). – x-yuri Feb 05 '23 at 22:12
5 Answers
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.

- 75,357
- 9
- 52
- 60
-
1This 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
-
-
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 -
4Please 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
-
4Hi, 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
-
6`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
-
2I 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
-
@Avi The "Docker way" is to have the container run a single command (in general your app/command should be PID 0) as the "entrypoint", so if you're doing things The Right Way™ you shouldn't be running crond as a daemon, which is what it sounds like you're expecting. That's the traditional way cron is run, but again, it's doesn't fit the containerization paradigm. When you grow your system(s) you'll want something monitoring and managing your containers. Logging outside the container comes from your command's STDIN/STDOUT and exit codes are returned to the container controller/monitor, eg K8s. – Joel Mellon Jun 08 '22 at 00:18
-
use his answer https://stackoverflow.com/a/45815035/1818723 because of this https://petermalmgren.com/signal-handling-docker/ – Pawel Cioch Dec 02 '22 at 21:29
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.

- 4,284
- 2
- 31
- 41
@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
...

- 10,412
- 1
- 35
- 28
-
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
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.

- 16,722
- 15
- 114
- 161
-
I'd like to ask @ChrisF about my deleted answer, if this one is tailored enough to the question. But apparently I can't mention him here. If you're going to delete this answer let's discuss first what's a duplicate, and what's not. Or give me some way of communication so that I could improve my answer. – x-yuri Feb 06 '23 at 06:55
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']

- 503
- 1
- 7
- 19
-
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