如何在Docker容器中运行定时任务(cron job)?

9
我有一个Python脚本,它将数据填充到AWS的Postgres数据库中。我可以手动运行它,并且它可以成功地将数据加载到数据库中。我想在每5分钟内在Docker容器中运行它一次。
因此,我将它包含在Docker镜像中以便运行。但我不确定为什么它没有运行。我无法看到任何追加到 `/var/log/cron.log` 文件中的内容。有人可以帮助我找出为什么它没有运行吗?
在docker build期间,我可以将脚本复制到映像中并手动运行它。数据库正在填充,并且我得到了预期的输出结果。
该脚本位于当前目录,将被复制到 `/code/` 文件夹中。
以下是我的代码: Dockerfile:
FROM python:3
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get install -y cron
RUN apt-get install -y postgresql-client
RUN touch /var/log/cron.log
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD . /code/
COPY crontab /etc/cron.d/cjob
RUN chmod 0644 /etc/cron.d/cjob
CMD cron && tail -f /var/log/cron.log

crontab:

*/5 * * * * python3 /code/populatePDBbackground.py >> /var/log/cron.log
# Empty line

1
可能是如何在Docker容器内运行cron作业?的重复问题。 - cgcgbcbc
我也看到了那个问题。但它并没有帮助到我。 - Underoos
不,我没有添加 tail -f 部分。那只是为了在 Docker 容器日志中显示文件的输出。我们可以使用 cat / var / log / cron.log 随时查看内容。如果我有错,请纠正我。是否必须添加 tail - Underoos
这不仅仅是为了在Docker日志中显示文件。Docker需要一个前台进程。tail -f将跟随日志文件并保持在前台。cron -f具有相同的效果。 - cgcgbcbc
我忘记正确设置权限了。所以 chmod 0644 /etc/cron.d/cjob 帮助了我。 - sergej
显示剩余3条评论
3个回答

22

Crontab需要额外的字段:运行命令的用户:

* * * * * root python3 /code/populatePDBbackground.py >> /var/log/cron.log
# Empty line

Dockerfile 是:

FROM python:3
RUN apt-get -y update && apt-get -y upgrade
RUN apt-get install -y cron postgresql-client
RUN touch /var/log/cron.log
RUN mkdir /code
WORKDIR /code
ADD . /code/
COPY crontab /etc/cron.d/cjob
RUN chmod 0644 /etc/cron.d/cjob
ENV PYTHONUNBUFFERED 1
CMD cron -f

测试Python脚本populatePDBbackground.py如下:

from datetime import datetime

print('Script has been started at {}'.format(datetime.now()))

最终我们得到:

$ docker run -d b3fa191e8822
b8e768b4159637673f3dc4d1d91557b374670f4a46c921e0b02ea7028f40e105

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
b8e768b41596        b3fa191e8822        "/bin/sh -c 'cron -f'"   4 seconds ago       Up 3 seconds                            cocky_beaver

$ docker exec -ti b8e768b41596 bash
root@b8e768b41596:/code# tail -f /var/log/cron.log
Script has been started at 2019-03-13 00:06:01.095013
Script has been started at 2019-03-13 00:07:01.253030
Script has been started at 2019-03-13 00:08:01.273926

1
谢谢你,我已经苦苦挣扎了很长时间。原来是在cron命令中缺少了“root”用户 - 在添加后,一切都正常了。 - Vidar

1

docker 中使用传统的 cron 实现比较棘手。考虑使用 supercronic

docker-compose.yml:

services:
  supercronic:
    build: .
    command: supercronic crontab

Dockerfile

FROM alpine:3.17
RUN set -x \
    && apk add --no-cache supercronic shadow \
    && useradd -m app
USER app
COPY crontab .

crontab

*/5 * * * * date

$ docker-compose up

更多的选择可以在我的其他答案中找到。


你介意详细解释为什么使用标准的cron有些棘手吗? - mapto
1
传统上,cron通过邮件报告失败情况。将结果在docker logs中可用要么是不可能的,要么是困难的,这取决于具体的实现方式。 - x-yuri

0
这可能并不直接相关,但我在运行 Docker 容器中的 cronjob 时卡住了。我尝试了已接受的答案,但没有成功。最后,我发现我用来编辑 Crontab 文件的编辑器(Notepad++)设置为 Windows 行尾(CR LF)。一旦我将其更改为 Unix 行尾(LF),我的 cronjob 就可以在 Docker 容器中成功运行了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接