我试图在调用shell脚本的docker容器内运行cronjob。
昨天我一直在网上搜索,堆栈溢出,但我真的找不到一个有效的解决方案。 我该怎么做呢?
我试图在调用shell脚本的docker容器内运行cronjob。
昨天我一直在网上搜索,堆栈溢出,但我真的找不到一个有效的解决方案。 我该怎么做呢?
当前回答
下面是我的基于docker-compose的解决方案:
cron:
image: alpine:3.10
command: crond -f -d 8
depends_on:
- servicename
volumes:
- './conf/cron:/etc/crontabs/root:z'
restart: unless-stopped
带有cron条目的行在./conf/cron文件中。
注意:这将不会运行不在alpine映像中的命令。
此外,任务的输出显然不会出现在docker日志中。
其他回答
您可以将crontab复制到映像中,以便从映像中启动的容器运行作业。
重要提示:docker-cron问题3中提到:cron文件使用LF,而不是CRLF。
参见Julien Boulay在他的Ekito/ Docker -cron中的“Run a cron job with Docker”:
让我们创建一个名为“hello-cron”的新文件来描述我们的工作。
# must be ended with a new line "LF" (Unix) and not "CRLF" (Windows)
* * * * * echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.
如果你想知道什么是2>&1,Ayman Hourieh解释道。
下面的Dockerfile描述了构建映像的所有步骤
FROM ubuntu:latest
MAINTAINER docker@ekito.fr
RUN apt-get update && apt-get -y install cron
# Copy hello-cron file to the cron.d directory
COPY hello-cron /etc/cron.d/hello-cron
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
# Apply cron job
RUN crontab /etc/cron.d/hello-cron
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log
但是:如果cron死亡,容器将继续运行。
(见Gaafar的评论和我如何使apt-get安装噪音更小?: Apt-get -y install -qq——force-yes cron也可以工作)
正如Nathan Lloyd在评论中所指出的:
关于一个问题的简单说明: 如果您正在添加一个脚本文件并告诉cron运行它,请记住这样做 运行chmod 0744 /the_script 如果你忘记了,Cron会默默地失败。
或者,确保你的作业本身直接重定向到stdout/stderr,而不是一个日志文件,如hugoShaka的回答所述:
* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2
将最后一行Dockerfile替换为
CMD ["cron", "-f"]
但是:如果你想以非根用户的身份运行任务,它就不起作用了。
参见(关于cron -f,这是说cron“前景”)“docker ubuntu cron -f不能正常工作”
构建并运行它:
sudo docker build --rm -t ekito/cron-example .
sudo docker run -t -i ekito/cron-example
耐心等待2分钟,你的命令行应该显示:
Hello world
Hello world
Eric在评论中补充道:
请注意,如果tail是在映像构建期间创建的,那么它可能不会显示正确的文件。 如果是这种情况,您需要在容器运行时创建或触摸该文件,以便tail获得正确的文件。
参见“docker CMD末尾的tail -f输出不显示”。
更多信息请参见Jason Kulatunga的“在Docker中运行Cron”(2021年4月),他在下面评论道
参见Jason的图片AnalogJ/docker-cron基于:
Dockerfile安装cronie/crond,取决于发行版。 一个入口点初始化/etc/environment,然后调用 Cron -f -l 2
我想分享一些我发现更灵活的其他建议的典型的修改。我想用一个环境变量来启用更改cron时间,最后添加了一个额外的脚本,在我的entrypoint.sh中运行,但在调用cron -f之前
*updatecron.sh*
#!/bin/sh
#remove old cron files
rm -rf /etc/cron.*/*
#create a new formatted cron definition
echo "$crondef [appname] >/proc/1/fd/1 2>/proc/1/fd/2" >> /etc/cron.d/restart-cron
echo \ >> /etc/cron.d/restart-cron
chmod 0644 /etc/cron.d/restart-cron
crontab /etc/cron.d/restart-cron
这将删除任何现有的cron文件,使用crondef的ENV变量创建一个新的cronfile,然后加载它。
VonC的回答相当彻底。此外,我想补充一件对我有帮助的事情。如果您只想运行一个cron作业而不跟踪文件,那么您可能会想从cron命令中删除&& tail -f /var/log/cron.log。
然而,这将导致Docker容器在运行后不久退出,因为当cron命令完成时,Docker认为上一个命令已经退出,因此杀死了容器。这可以通过在前台通过cron -f运行cron来避免。
我决定使用busybox,因为它是最小的图像之一。
crond在前台(-f)执行,日志发送到stderr (-d),我没有选择更改日志级别。 Crontab文件拷贝到默认路径:/var/spool/ Crontab
FROM busybox:1.33.1
# Usage: crond [-fbS] [-l N] [-d N] [-L LOGFILE] [-c DIR]
#
# -f Foreground
# -b Background (default)
# -S Log to syslog (default)
# -l N Set log level. Most verbose 0, default 8
# -d N Set log level, log to stderr
# -L FILE Log to FILE
# -c DIR Cron dir. Default:/var/spool/cron/crontabs
COPY crontab /var/spool/cron/crontabs/root
CMD [ "crond", "-f", "-d" ]
但是任务的输出显然不能在docker日志中看到。
只要添加到答案列表中,你也可以使用这张图片: https://hub.docker.com/repository/docker/cronit/simple-cron
并使用它作为启动cron作业的基础,像这样使用它:
FROM cronit/simple-cron # Inherit from the base image
#Set up all your dependencies
COPY jobs.cron ./ # Copy your local config