5

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
  • Have you created /var/spool/cron/crontabs inside the container? – Rui F Ribeiro Jul 2 '18 at 12:20
  • @RuiFRibeiro no (however the directory exists). Tell me more. – ctrl-alt-delor Jul 2 '18 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. – ctrl-alt-delor Jul 2 '18 at 12:39
7

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://hg@bitbucket.org/davids_dad/a_website

  • Would you explain how touching it makes the difference? It got me curious. – Rui F Ribeiro Jul 5 '18 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. – ctrl-alt-delor Jul 6 '18 at 7:46
  • Makes sense, will have to remember investigating it. thanks. – Rui F Ribeiro Jul 6 '18 at 7:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.