【问题标题】:Inside Docker container, cronjobs are not getting executed在 Docker 容器内,cronjobs 没有被执行
【发布时间】:2015-06-06 03:09:36
【问题描述】:

我已经从 Dockerfile 制作了一个 Docker 映像,并且我希望在基于此映像的容器运行时定期执行一个 cronjob。我的 Dockerfile 是这样的(相关部分):

FROM l3iggs/archlinux:latest

COPY source /srv/visitor

WORKDIR /srv/visitor

RUN pacman -Syyu --needed --noconfirm \
        && pacman -S --needed --noconfirm make gcc cronie python2 nodejs phantomjs \
        && printf "*/2 * * * *       node /srv/visitor/visitor.js \n" >> cronJobs \
        && crontab cronJobs \
        && rm cronJobs \
        && npm install -g node-gyp \
        && PYTHON=/usr/sbin/python2 && export PYTHON \
        && npm install

EXPOSE 80

CMD ["/bin/sh", "-c"]

创建映像后,我运行一个容器并验证确实已添加 cronjob:

crontab -l

*/2 * * * *     node /srv/visitor/visitor.js

现在,问题是 cronjob 永远不会执行。当然,我已经测试过“node /srv/visitor/visitor.js”在从控制台手动运行时可以正确执行。

有什么想法吗?

【问题讨论】:

  • cron 需要一个守护进程。一半的过程正在创建作业,该作业驻留在 cron 的文件存储中。 cron 的另一半是执行作业。你可以看看:stackoverflow.com/questions/20545554/…。如果您希望主机的 cron 守护进程执行您的 cron 工作,您可能需要在启动容器时挂载主机的 cron 目录?不过这听起来不太好!
  • 格雷格,你为什么不把它添加为答案?我正要说同样的话。另请注意,Phusion 映像是在运行 cron 时提供的。
  • @Greg 我现在可以理解你在说什么了。问题是,我不想挂载主机的 cron 目录,也不想在容器内运行 systemd(根据其他一些建议)。我觉得这两种方法都会不必要地“污染”原本干净的系统。我的替代方案是什么?我可以在没有 systemd 的情况下运行 cronie 吗?或者,有其他选择吗?
  • @dsljanus Greg 给你的链接中的建议有什么问题?如果你想运行 cron 和另一个进程,你必须要么在入口点/cmd 脚本中处理它,要么使用 systemd/supervisor/runit 等。
  • @dsljanus 为什么你不能?唯一的问题是如果你不能让它停止分叉到后台。 CMD cron -f工作吗?

标签: cron docker


【解决方案1】:

要明确回答这个问题有点棘手,因为我没有时间测试,但您有多种选择:

  • 您可以使用 Phusion 基础镜像,它带有一个 init 系统和安装的 cron。它基于 Ubuntu,相对重量级(至少与 archlinux 相比)https://registry.hub.docker.com/u/phusion/baseimage/

  • 如果您乐于从 cron 作业开始一切,您可以从 CMD 开始 cron 并将其保留在前台 (cron -f)。

  • 您可以使用轻量级进程管理器来启动 cron 以及您需要的任何其他进程(Phusion 使用 runit,Docker 似乎推荐 supervisor)。

  • 您可以编写自己的 CMDENTRYPOINT 脚本来启动 cron 和您的进程。唯一的问题是您需要小心正确处理信号,否则您可能会遇到僵尸进程。

在你的情况下,如果你只是玩玩,我会选择最后一个选项,如果更严重,我会选择流程管理器。

【讨论】:

  • 首先,感谢您的详尽回答。我倾向于使用第二个选项,使用 CMD 命令运行 cron,因为我想做的就是每 2 分钟无限运行一个命令。事情是,Arch 没有“cron”,因为 cronie 是一个售后软件包。另外,如果这是 oveecome,我可以在后台运行 cron 吗?因此,如果我愿意,我可以附加到容器上。
  • 我对 cronie 一无所知,但我希望它也能正常工作。你仍然可以使用docker exec -it CONTAINER /bin/bash 进入容器,所以这不是问题。
  • 在运行的容器内,crond 正在运行,并通过“ps -aux | grep cron”进行验证。当然是手动说明的。问题是,仍然没有执行 cronjobs。
  • 酷,那么你已经接近了。我怀疑它现在只是一个 cron 配置问题;也许它没有拾取您的配置文件或其他东西。
  • crontab 文件正确设置了我的作业。如果守护进程也在运行,还需要配置什么?
【解决方案2】:

一种选择是通过以下方式使用主机的 crontab:

0 5 * * * docker exec mysql mysqldump --databases myDatabase -u myUsername -pmyPassword > /backups/myDatabase.sql

以上将定期对 MySQL 数据库进行每日备份。

如果您需要链接复杂的命令,您也可以使用这种格式:

0 5 * * * docker exec mysql sh -c 'mkdir -p /backups/`date +\%d` && for DB in myDB1 myDB2 myDB3; do mysqldump --databases $DB -u myUser -pmyPassword > /backups/`date +\%d`/$DB.sql; done'

上面需要对多个数据库进行 30 天的滚动备份,并在一行中执行 bash for 循环,而不是编写和调用 shell 脚本来执行相同的操作。所以它非常灵活。

或者您也可以将复杂的脚本放入 docker 容器中并像这样运行它们:

0 5 * * * docker exec mysql /dailyCron.sh

【讨论】:

  • 这种方式不能帮你保持应用端的任务配置。
【解决方案3】:

如果您使用 --net=host 运行 Docker 容器,请参阅此线程: https://github.com/docker/docker/issues/5899

我遇到了同样的问题,当我在 docker run 命令行参数中包含 --pid=host 时,我的 cron 任务开始运行。

【讨论】:

    猜你喜欢
    • 2015-10-17
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 2023-01-04
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多