当我启动我的 docker 容器时,Cron 没有运行

Posted

技术标签:

【中文标题】当我启动我的 docker 容器时,Cron 没有运行【英文标题】:Cron isn't running when I start my docker container 【发布时间】:2017-03-03 23:34:30 【问题描述】:

作为序言,我一直在参考这两篇文章寻求帮助:

Run a cron job with Docker - Julien Boulay Running cron jobs inside a Docker container - Chris S.

我的目标是在我启动 docker 容器时自动启动一个 cron 作业。目前,它不会自动启动,但我可以手动进入我的容器并运行service cron start,它会启动作业,并且它可以正常工作。

所以问题是:如何让我的 cron 作业在我的容器启动时自动启动?

Dockerfile

FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y cron

COPY . /app

WORKDIR /app

ADD crontab /etc/cron.d/crontab
RUN chmod 0600 /etc/cron.d/crontab
RUN crontab -u root /etc/cron.d/crontab
RUN touch /var/log/cron.log

RUN ["dotnet", "restore"]

RUN ["dotnet", "build"]

EXPOSE 5000/tcp

CMD cron && tail -f /var/log/cron.log
CMD service cron start

crontab

* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# Empty space

虽然我无法让 cron 在该特定容器中工作,但我能够创建一个专门用于 cron 的独立 docker 容器,并且成功地让它自动运行。

至于 cron 容器的设置,我按照链接的文章 Run a cron job with Docker - Julien Boulay 进行操作,并且能够使其正常工作。

【问题讨论】:

您是否需要在容器内运行 cron,或者您是否可以在主机上创建一个 cron 作业以在所需时间运行此容器以完成其工作? @R0MANARMY 它需要在容器内运行。 你已经看过this question ? @R0MANARMY 是的,这个问题基本上只是概述了我的第一个参考。 根据Docker docs,Dockerfile 中只能有一条 CMD 指令。我建议取出第二个。看起来您的 Dockerfile 与另一个答案中的差异只有几个。我会尝试一次更改那些,看看你是否可以让它运行。 【参考方案1】:

我正在做的是让 CMD 像这样直接调用 cron:

CMD /usr/sbin/cron -f

在此之前,我将 crontab 添加到容器并使用以下命令将其分配为根 crontab:

RUN crontab /root/mycrontab

您不需要对位于/etc/cron.d 中的文件调用 crontab 命令,但您确实需要这些文件具有正确的语法。使用你的例子,而不是这个:

* * * * * echo "Hello world" >> /var/log/cron.log 2>&1

你应该有这个:

* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1

在您的 crontab 文件中。这仅适用于位于/etc/cron.d 内的 crontab 文件,否则您的 crontab 文件语法是正确的,您可以使用 crontab 命令加载它。

从你的例子开始,我认为你应该像这样修改你的文件:

Dockerfile

FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y cron

COPY . /app

WORKDIR /app

ADD crontab /etc/cron.d/crontab
RUN chmod 0600 /etc/cron.d/crontab
RUN touch /var/log/cron.log

RUN ["dotnet", "restore"]

RUN ["dotnet", "build"]

EXPOSE 5000/tcp

CMD /usr/sbin/cron -f

crontab

* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1

另一种选择是:

Dockerfile

FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y cron

COPY . /app

WORKDIR /app

ADD crontab /root/
RUN crontab /root/crontab
RUN touch /var/log/cron.log

RUN ["dotnet", "restore"]

RUN ["dotnet", "build"]

EXPOSE 5000/tcp

CMD /usr/sbin/cron -f

crontab

* * * * * echo "Hello world" >> /var/log/cron.log 2>&1

【讨论】:

感谢您的回复!我很难跟踪你。您介意编辑您的答案以显示我的 Dockerfilecrontab 文件的样子吗?谢谢! 我尝试了您的两个版本的答案,但仍然无法正常工作。我可以提供任何其他信息来提供更好的帮助吗? 我刚刚使用第二个版本(从 dockerfile 中删除了 dotnet restore 和 build 命令)对其进行了测试,并且 cron 可以正常工作。你能进入容器里面看看 cron 是否正在运行吗? (例如:ps auxw|grep cron 所以我正在做的是; docker-compose builddocker-compose up -d,然后我通过docker exec -it container-id bash进入我的容器,然后通过service cron status检查cron是否正在运行,返回cron is not running ... failed! 我尝试使用相同的命令,但对我来说service cron status 返回cron is running.。我正在使用 4.4.0.45 通用内核的 ubuntu 机器上进行测试。您是在 Windows 机器上进行测试吗?【参考方案2】:

我们遇到了 php-fpm 和 docker 问题,无法执行我们的 cronjob 任务。我们解决了两个问题:

我们尝试使用COPY config/custom-cron /etc/cron.d/custom-croncrontab 文件复制到docker 容器中。问题是,我们的行尾windows格式的。这确实破坏了我们的 crontab 文件,因为在将该文件复制到容器中时不会转换此行结尾。 第二个问题是,我们试图通过CMD ["cron", "-f"] 启动cron,这确实阻塞了php-fpm 主进程。这会导致在调用我们的 Web 应用程序时出现502 Bad gateway 错误。

最后,我们通过手动编辑 crontab 文件来实现它,同时构建 docker 映像而不是复制粘贴,并使用 supervisord 在 docker 内运行多个任务。这应该适用于所有受支持的操作系统。

码头文件

FROM php:7.1.16-fpm

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

# Configure cron
RUN crontab -l |  cat; echo "* * * * * echo 'Hello world' >> /var/log/cron-test.log 2>&1";  | crontab -

# Configure supervisor
COPY config/supervisord.conf /etc/supervisor/supervisord.conf

supervisord.conf

[supervisord]
logfile = /dev/null
loglevel = info
pidfile = /var/run/supervisord.pid
nodaemon = true

[program:php-fpm]
command = php-fpm
autostart = true
autorestart = true
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

[program:cron]
command = cron -f
autostart = true
autorestart = true
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

【讨论】:

非常感谢您指出这一点!我们注意到,我们的 laravel 计划作业突然停止在 PROD 应用程序中工作,并且不知道为什么。事实证明,这个问题是在我们部署了一个在 Windows 上构建的 docker 容器之后开始的。以前我们只部署了基于 Linux 构建的容器。我刚刚将 crontab 转换为 UNIX 格式并且能够解决这个问题,即使是从 Windows 机器上部署的。再次感谢!【参考方案3】:

基于 Debian 的发行版中存在一个错误,这将导致 cronjobs 失败,因为 docker 使用分层文件系统并且 cron 无法启动并显示 NUMBER OF HARD LINKS > 1 (/etc/crontab)

修复很简单,将touch /etc/crontab /etc/cron.*/* 添加到容器的入口点。

我在这里发表了一篇博文,解释如何在 Docker 容器中设置 cron:https://esc.sh/blog/cron-jobs-in-docker/

【讨论】:

仅供参考:您博客的证书似乎已过期。无法通过 Safari 访问。 非常感谢伙计。我已经更改了域名。修复它:)【参考方案4】:

我知道这是一个老问题,但我在 Debian 上找到了解决这个问题的方法,它解决了我的问题。带有 uid 的 Cron pam auth 使我的 cron 无法运行。

RUN sed -i '/session    required     pam_loginuid.so/c\#session    required     pam_loginuid.so/' /etc/pam.d/cron

【讨论】:

以上是关于当我启动我的 docker 容器时,Cron 没有运行的主要内容,如果未能解决你的问题,请参考以下文章

如何在 docker 容器中运行 cron 作业

如何在 Docker 容器中以非 root 用户身份启动 cron?

Python 脚本在 docker 容器中找不到使用 CRON 运行的 ENV 变量

我运行启动 tomcat8 服务器的 docker 映像,但它没有启动

用于laravel的docker容器上的cron无法正常工作

在我将 cron 文件重新保存在 docker 容器中之前,Cron 作业不起作用