【问题标题】:crontab not being executed until file is edited (crontab setup with Dockerfile)在编辑文件之前不会执行 crontab(使用 Dockerfile 设置 crontab)
【发布时间】:2021-05-07 23:43:09
【问题描述】:

在 ubuntu 机器上,我有一个使用 Dockerfile 设置的 crontab:

...

RUN apt-get update && apt-get install -y cron

...

ADD crontab /etc/cron.d/crontab

RUN chmod 0644 /etc/cron.d/crontab

RUN systemctl enable cron

RUN touch /etc/cron.d/crontab

crontab:

15 17 * * * root /home/misc/runSomething.sh

创建容器后它没有按时触发,但是如果我用 vi 手动编辑文件来测试它,它会在之后工作。直到它被编辑,它似乎被拾起。有没有人知道如何解决这个问题?

请注意,所有权等不会因编辑而改变:

root@machine:/home/gradle/src# ls -la /etc/cron.d
...
-rw-r--r-- 1 root root  50 Feb  3 14:55 crontab
...
root@machine:/home/gradle/src# vi /etc/cron.d/crontab
...
root@machine:/home/gradle/src# ls -la /etc/cron.d
...
-rw-r--r-- 1 root root  51 Feb  3 15:42 crontab

【问题讨论】:

  • 在 Dockerfile 中运行 systemctl enable cron 通常不会完成任何有用的事情(因为 systemd 可能未配置为在容器启动时启动)。您能向我们展示您的完整 Dockerfile 吗?
  • 谢谢,@larsks ...我已将其删除并重新测试了我将在下面的答案中描述的修复程序,它正在工作。本质上,dockerfile 的其余部分只是 apt-get 调用和证书安装

标签: docker ubuntu cron


【解决方案1】:

我不知道如何使 /etc/cron.d 中的文件与 docker 一起正常工作,但我确实找到了一种解决方法,我将分享给其他人。如果有人确实知道如何将 /etc/cron.d 文件与 docker 一起使用,我将不接受我的答案。

我在这篇帖子中注意到How to run a cron job inside a docker container 这一行:

... 
the files under /etc/cron.d/ are read and interpreted by cron as soon as edited
...

这让我觉得我遇到的是预期的功能。

然后我相应地修改了我的搜索并找到了这个:How to run a cron job inside a docker container

所以我修改了我的 dockerfile 以像这样设置 crontab:

ADD crontab /home/gradle/src/crontab

RUN /usr/bin/crontab /home/gradle/src/crontab

这更容易且有效。请注意,正如@larsks 提到的,不需要“systemctl enable cron”。

我同意@DavidMaze 和@lazyhead 的观点,即我不应该将“cron && gradle bootrun”作为我的命令,但这只是暂时的情况。 cron 最终会为这个容器输出命令。

【讨论】:

    【解决方案2】:

    一个常见的最佳做法是每个容器有 1 个进程。对于容器内的单个进程,在发生错误等情况下组织容器的正常关闭要容易得多。

    如果您要添加 cron,您将至少有 2 个进程,因此:

    1. 您真的需要在您的应用程序中使用 cron 进程吗?例如,您可以使用docker exec -it <yourcontainer> <required-command> 定期从外部访问您的容器
    2. 确保cron 进程在您的应用程序启动期间启动,因此您可以使用类似
      ENTRYPOINT cron && yourapp
      CMD cron && yourapp
      

    据我了解RUN 命令只是修改文件系统层,但是它不会启动后台进程等等。

    【讨论】:

    • 由于一个常见的最佳实践是每个容器有 1 个进程,因此通常最好执行CMD cron -f 之类的操作来运行前台 cron 进程作为其容器中的唯一进程,或者使用 docker run your-image cron -f在启动时指定备用命令。
    • 同意。我确实有 cron && gradle bootrun 作为我的命令,我知道这不是最佳实践。不过,这只是暂时的。我只是将一些在 Spring Boot 应用程序中使用 @Scheduled 在线程中处理的功能外部化。我将取出 cron 并让另一个容器尽快进行这些调用,但与此同时我只是想要一个解决方法。
    猜你喜欢
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 2016-07-19
    • 1970-01-01
    • 2020-10-19
    • 2014-11-11
    相关资源
    最近更新 更多