Question
I am trying to run a cronjob inside a docker container that invokes a shell script.
Yesterday I have been searching all over the web and stack overflow, but I
could not really find a solution that works.
How can I do this?
Answer
You can copy your crontab
into an image, in order for the container launched
from said image to run the job.
Important : as noted in docker-cron issue
3: use LF, not
CRLF for your cron
file.
See "Run a cron job with Docker" from
Julien Boulay in his Ekito/docker- cron
:
Let’s create a new file called "
hello-cron
" to describe our job.
# must be ended with a new line "LF" (Unix) and not "CRLF" (Windows)
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.
If you are wondering what is 2>&1
, Ayman
Hourieh
explains.
The following Dockerfile describes all the steps to build your image
FROM ubuntu:latest
MAINTAINER [[email protected]](/cdn-cgi/l/email-protection)
RUN apt-get update && apt-get -y install cron
# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
But: ifcron
dies, the container keeps
running.
(see Gaafar's
[comment](https://stackoverflow.com/questions/37458287/how-to-run-a-cron-job-
inside-a-docker-container/37458519?noredirect=1#comment67411829_37458519) and
[How do I make apt-get
install less
noisy?](https://askubuntu.com/questions/258219/how-do-i-make-apt-get-install-
less-noisy#comment326577_258226):
apt-get -y install -qq --force-yes cron
can work too)
As noted by [Nathan Lloyd](https://stackoverflow.com/users/3417592/nathan- lloyd) in [the comments](https://stackoverflow.com/questions/37458287/how-to- run-a-cron-job-inside-a-docker-container/37458519#comment107451752_37458519):
Quick note about a gotcha:
If you're adding a script file and telling cron to run it, remember to
RUN chmod 0744 /the_script
Cron fails silently if you forget.
OR, make sure your job itself redirect directly to stdout/stderr instead of a log file, as described in hugoShaka's answer:
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
Replace the last Dockerfile line with
CMD ["cron", "-f"]
But: it doesn't work if you want to run tasks as a non- root.
See also (about cron -f
, which is to say cron "foreground") "docker ubuntu
cron -f
is not working"
Build and run it:
sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example
Be patient, wait for 2 minutes and your command-line should display:
Hello world
Hello world
Eric adds [in the comments](https://stackoverflow.com/questions/37458287/how-to-run-a-cron-job- inside-a-docker-container/37458519#comment84898391_37458519):
Do note that
tail
may not display the correct file if it is created during image build.
If that is the case, you need to create or touch the file during container runtime in order for tail to pick up the correct file.
See "Output of tail -f
at the end of a docker CMD
is not
showing".
See more in "[ Running Cron in Docker](https://blog.thesparktree.com/cron- in-docker)" (Apr. 2021) from Jason Kulatunga, as he [commented below](https://stackoverflow.com/questions/37458287/how-to-run-a- cron-job-inside-a-docker-container/37458519#comment118918017_37458519)
See Jason's image [AnalogJ/docker-cron
](https://github.com/AnalogJ/docker-
cron) based on:
-
Dockerfile installing
cronie
/crond
, depending on distribution. -
an entrypoint initializing
/etc/environment
and then callingcron -f -l 2