当我启动我的 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
【讨论】:
感谢您的回复!我很难跟踪你。您介意编辑您的答案以显示我的 Dockerfile 和 crontab 文件的样子吗?谢谢! 我尝试了您的两个版本的答案,但仍然无法正常工作。我可以提供任何其他信息来提供更好的帮助吗? 我刚刚使用第二个版本(从 dockerfile 中删除了 dotnet restore 和 build 命令)对其进行了测试,并且 cron 可以正常工作。你能进入容器里面看看 cron 是否正在运行吗? (例如:ps auxw|grep cron
)
所以我正在做的是; docker-compose build
,docker-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-cron
将crontab
文件复制到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 容器中以非 root 用户身份启动 cron?
Python 脚本在 docker 容器中找不到使用 CRON 运行的 ENV 变量
我运行启动 tomcat8 服务器的 docker 映像,但它没有启动