【问题标题】:Cron containers for docker - how do they actually work?用于 docker 的 Cron 容器 - 它们实际上是如何工作的?
【发布时间】:2015-11-21 18:28:44
【问题描述】:

我已经使用 docker 几个月了,并且正在对各种不同的服务器映像进行 docker 化。一个一致的问题是许多服务器需要运行 cron 作业。网上有很多关于这个的讨论(包括在 Stackoverflow 上),但我并不完全理解它的机制。

目前,我在每个容器中使用主机的 cron 和 docker exec 来运行脚本。我创建了一个关于脚本名称和位置的约定;我所有的容器都有相同的脚本。这避免了主机的 cron 依赖于容器。

基本上,主机的 cron 每分钟执行一次:

for each container
   docker exec -it <containername> /cronscript/minute-script

这可行,但会使容器依赖于主机。

我想做的是创建一个 cron 容器,它在每个其他容器中启动一个脚本 - 但我不知道有一个等效于从一个容器到另一个容器的“docker exec”。

我现在的具体情况是在 MySQL 容器中运行备份,并且运行 Moodle 要求每分钟运行一次的 cron 作业。最终,我需要通过 cron 做一些额外的事情。 Moodle 使用命令行 PHP 脚本。

在另一个容器中从一个容器启动脚本的“正确”泊坞化方式是什么?

更新:也许提及我的具体用例会有所帮助,尽管随着时间的推移会有更多。

目前,cron需要做以下事情:

  • 从 MySQL 执行数据库转储。我可以通过 cron 容器中的 mysqldump TCP 链接做到这一点;这里的缺点是我不能将备份用户限制为主机 127.0.0.1。我还可以通过卷以某种方式将 MySQL 套接字连接到 cron 容器中。
  • 对 Moodle 安装执行定期维护。 Moodle 包含一个运行所有维护任务的 php 命令行脚本。这对我来说是个大问题。我可以可能在一个卷中运行这个脚本,但 Moodle 的设计并没有考虑到这种情况,我不会排除竞争条件。另外,我不希望将 moodle 安装在卷中,因为这会使更新容器变得更加困难(请记住,在 Docker 中,使用新映像更新容器时不会重新初始化卷)。
  • 未来:对我的许多其他服务器执行例行维护,例如清理电子邮件队列等。

【问题讨论】:

标签: cron docker


【解决方案1】:

我的解决办法是:

  • 在容器内安装 crond
  • 安装你的软件
  • 将 cron 作为守护进程运行
  • 运行你的软件

我的Dockerfile的一部分

FROM debian:jessie

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY .crontab /usr/src/app

# Set timezone
RUN echo "Europe/Warsaw" > /etc/timezone \
    && dpkg-reconfigure --frontend noninteractive tzdata

# Cron, mail
RUN set -x \
    && apt-get update \
    && apt-get install -y cron rsyslog mailutils --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

CMD rsyslogd && env > /tmp/crontab && cat .crontab >> /tmp/crontab && crontab /tmp/crontab && cron -f

说明

  1. 设置时区,因为 cron 需要它来正确运行任务
  2. 安装 cron 包 - 带有 cron 守护程序的包
  3. 安装rsyslog包来记录cron任务输出
  4. 如果您想从 cron 任务发送电子邮件,请安装 mailutils
  5. 运行rsyslogd
  6. 将 ENV 变量复制到 tmp 文件,因为 cron 运行具有最小 ENV 的任务,而您的任务可能需要访问容器 ENV 变量
  7. 将您的 .crontab 文件(包含您的任务)附加到 tmp 文件中
  8. 从 tmp 文件设置根 crontab
  9. 运行 cron 守护进程

我在我的容器中使用它并且工作得很好。

每个容器一个进程

如果你喜欢这个范例,那么为每个 cron 任务创建一个 Dockerfile。例如

  • Dockerfile - 主程序
  • Dockerfile_cron_task_1 - cron 任务 1
  • Dockerfile_cron_task_1 - cron 任务 2

并构建所有容器:

docker build -f Dockerfile_cron_task_1 ...

【讨论】:

  • 谢谢!我可以看到这个解决方案是如何工作的,但我打破了每个容器一个进程的范式。不过,我喜欢这样可以将所有内容都包含在同一个容器中,并且我实际上可能会使用此解决方案;看来这个问题没有真正好的解决方案。
  • 我注意到您对答案的补充(每个容器一个进程),它确实解决了关注点的分离,但最后,它仍然遇到同样的问题,唯一的选择从 cron 容器到主容器的通信要么通过共享卷,要么通过链接。您的架构允许 cron 对主容器有更多的了解,因此它实际上可以解决至少 80% 的实际用例。
猜你喜欢
  • 1970-01-01
  • 2013-09-27
  • 2017-10-26
  • 1970-01-01
  • 2016-10-05
  • 2021-01-21
  • 2011-09-27
  • 2021-12-16
  • 2013-03-14
相关资源
最近更新 更多