web-dev-qa-db-ja.com

cronをdockerで動作させる

Dockerでnginxを使用しています。 SSL証明書とDNS登録を更新するようにcronジョブを構成しました。ただし、cronジョブは実行されていません。

私が何をした。 arm32v7/nginxに基づいてDockerfileを作成しました。このインターンはdebian:stretch-slimに基づいています。最初にcronをインストールして実行すると想定しましたが、サービスが開始されていないことがわかりました(initサブシステムがインストールされていないため、debian:stretch-slimは非常に最小限です)。そこで、cronを開始するコードを追加しました。 cronが実行されているかどうかをコンテナに尋ねると、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.

ただし、cronに追加したタスクのログは表示されません。

run-parts --report /etc/cron.dailyを実行すると、私のタスクが実行され、ログ出力が生成されます。そのため、cronが実行されていないように見えます。

#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

つまり、cronがジョブを実行していないのはなぜですか?何を逃したのですか?

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
8
ctrl-alt-delor

rsyslogをインストールして、どのエラーが発生しているかを確認しました。

(*system*) NUMBER OF HARD LINKS > 1 (/etc/crontab)。少し検索したところ、cronには、ファイルへのハードリンクが多数ある場合は機能しないというセキュリティポリシーがあることがわかりました。残念ながら、Dockerの階層化ファイルシステムは、ファイルに多数のハードリンクを作成します。

これを修正するために、cronを実行する前に、起動スクリプトにtouch /etc/crontab /etc/cron.*/*を追加しました。これにより、他のファイルインスタンスからの接続が解除されます。

新しいエントリポイントは

#!/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 "$@"

私はテストし、それは動作します

概要

cronを動作させるには、必要があります。

  • インストールcron —インストールされていない場合
  • Cronジョブを/etc/cron.daily/(または毎週)に追加します。スクリプト名に文字、数字、ハイフンのみが含まれていることを確認しますドットなし。 (質問しないでください)参照 cronジョブがcron.dailyから実行されていない
  • crons構成ファイルのハードリンク数を1に減らします:do touch /etc/crontab /etc/cron.*/* —(dockerの場合)。起動スクリプトに入れました。
  • Start cronservice cron start —(基本OSの場合、初期化なし。Dockerで使用する多くの基本イメージと同様)起動スクリプトに入れました。

この回答のエントリポイントスクリプトと、質問のその他すべてがそれを実行します。現在のプロジェクトはhg clone ssh://[email protected]/davids_dad/a_websiteで取得できます

10
ctrl-alt-delor