15

I am using nginx in docker. I have configured cron jobs to update SSL certificates and DNS registration. However the cron jobs are not running.

What have I done. I have created a Dockerfile based on arm32v7/nginx this intern is based on debian:stretch-slim. At first I installed cron, 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 start cron. Now if I ask the container if cron 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 if cron 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
3
  • Have you created /var/spool/cron/crontabs inside the container? Jul 2, 2018 at 12:20
  • @RuiFRibeiro no (however the directory exists). Tell me more. Jul 2, 2018 at 12:34
  • I have as /etc/crontab and /etc/cron.daily/1-reginter-dns. They are listed in question. The /etc/crontab it the one that came with the instillation (it is not edited). It looks like it says once per day do cd / && run-parts --report /etc/cron.daily. But it is not doing it. If I type that into the shell, it does it. Jul 2, 2018 at 12:39

1 Answer 1

16

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 crons config files down to one: do touch /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

3
  • Would you explain how touching it makes the difference? It got me curious. Jul 5, 2018 at 19:15
  • 1
    @RuiFRibeiro I think it is because it makes it a different instance of the file, in the layered file-system, that docker uses. Jul 6, 2018 at 7:46
  • Makes sense, will have to remember investigating it. thanks. Jul 6, 2018 at 7:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .