Getting cron to work on docker
I installed rsyslog
to see what errors I was getting I got the following
(*system*) NUMBER OF HARD LINKS > 1 (/etc/crontab)
. A bit of searching told me that cron
has a security policy to not work if there are lots of hard-links to its files. Unfortunately Docker's layered file-system makes files have lots of hard-links.
To fix it, I added touch /etc/crontab /etc/cron.*/*
, to the start up script, before running cron
. This dis-attaches if from the other file-instances.
The new entrypoint is
#!/bin/sh
#fix link-count, as cron is being a pain, and docker is making hardlink count >0 (very high)
touch /etc/crontab /etc/cron.*/*
service cron start
# Hand off to the CMD
exec "$@"
I have tested and it works
Summary
To get cron
to work you will have to.
- Install
cron
— if not installed - Add cron job to
/etc/cron.daily/
(or weekly). Ensure that your script-name, has only letters, numbers, hyphens, no dots. (Don't ask) see cron job not running from cron.daily - Get the hardlink count of
cron
s config files down to one: dotouch /etc/crontab /etc/cron.*/*
— (if in docker). I put it in the start-up script. - Start
cron
:service cron start
— (If on a basic OS, with no init. As in a lot of base images for use in docker). I put it in the starts-up script.
The entrypoint script from this answer, and everything else from the question, will do it. Current project can be fetched with hg clone ssh://[email protected]/davids_dad/a_website
Related videos on Youtube
ctrl-alt-delor
A software engineer, programmer, project manager, Gnu+Linux user, Newly Qualified Teacher of computing. I am currently hanging out on A new site for computer science and IT educators. Visit the site here
Updated on September 18, 2022Comments
-
ctrl-alt-delor over 1 year
I am using
nginx
in docker. I have configuredcron
jobs to update SSL certificates and DNS registration. However thecron
jobs are not running.What have I done. I have created a
Dockerfile
based onarm32v7/nginx
this intern is based ondebian:stretch-slim
. At first I installedcron
, and assumed that it would run, but then discovered that the service was not started (there is no init subsystem installed, debian:stretch-slim is very minimal). So I added code to startcron
. Now if I ask the container ifcron
is running it says yes.#ctrl-alt-delor@raspberrypi:~/a_website/docker$ #↳ docker exec -it $(docker container ls | sed -nr -e 's/.*(website-stack.*)/\1/p') service cron status [ ok ] cron is running.
However I am not seeing any logs from the task that I have added to
cron
.If I run
run-parts --report /etc/cron.daily
, the my tasks get run, and produce log output. Therefore it still appears as ifcron
is not running.#ctrl-alt-delor@raspberrypi:~/a_website/docker$ #↳ docker exec -it $(docker container ls | sed -nr -e 's/.*(website-stack.*)/\1/p') cat /proc/12/cmdline; echo /usr/sbin/cron
So why is
cron
not running its jobs? What have I missed?Dockerfile
FROM arm32v7/nginx ##add backports COPY stretch-backports-source.list /etc/apt/sources.list.d/ ##install cron and curl — so we can register dns regularly RUN apt-get update &&\ apt-get install -y cron curl &&\ apt-get clean ##setup cron to register dns COPY register-dns register-dns.auth register-dns-hostname /usr/local/bin/ COPY register-dns.cron /etc/cron.daily/1-register-dns RUN chmod +x /usr/local/bin/register-dns /etc/cron.daily/1-register-dns ##add curtbot RUN apt-get update && \ apt-get -t stretch-backports install -y python-certbot-nginx && \ apt-get clean #add ssl port EXPOSE 443 80 ##custom entry point — needed by cron COPY entrypoint /entrypoint RUN chmod +x /entrypoint ENTRYPOINT ["/entrypoint"] CMD ["nginx", "-g", "daemon off;"] #:tricky: we seem to need to re-specify this LABEL name="my-nginx" \ description="nginx + cron + curl + certbot + dns-registering"
entrypoint
#!/bin/sh ## Do whatever you need with env vars here ... service cron start # Hand off to the CMD exec "$@"
/etc/crontab
SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
/etc/cron.daily/1-register-dns
#!/bin/sh date >> /var/log/register-dns /usr/local/bin/register-dns >>/var/log/register-dns
-
Rui F Ribeiro almost 6 yearsHave you created
/var/spool/cron/crontabs
inside the container? -
ctrl-alt-delor almost 6 years@RuiFRibeiro no (however the directory exists). Tell me more.
-
-
Rui F Ribeiro almost 6 yearsWould you explain how touching it makes the difference? It got me curious.
-
ctrl-alt-delor almost 6 years@RuiFRibeiro I think it is because it makes it a different instance of the file, in the layered file-system, that docker uses.
-
Rui F Ribeiro almost 6 yearsMakes sense, will have to remember investigating it. thanks.