我试图在调用shell脚本的docker容器内运行cronjob。

昨天我一直在网上搜索,堆栈溢出,但我真的找不到一个有效的解决方案。 我该怎么做呢?


当前回答

从上面的例子中,我创建了这样的组合:

在Nano中使用Crontab编辑高山图像(我讨厌vi)

FROM alpine

RUN apk update
RUN apk add curl nano

ENV EDITOR=/usr/bin/nano 

# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]

# Shell Access
# docker exec -it <CONTAINERID> /bin/sh

# Example Cron Entry
# crontab -e
# * * * * * echo hello > /proc/1/fd/1 2>/proc/1/fd/2
# DATE/TIME WILL BE IN UTC

其他回答

虽然这旨在通过Docker的exec接口在容器中运行进程的旁边运行作业,但您可能会感兴趣。

我已经编写了一个守护进程,用于观察容器并调度在其元数据中定义的作业。例子:

version: '2'

services:
  wordpress:
    image: wordpress
  mysql:
    image: mariadb
    volumes:
      - ./database_dumps:/dumps
    labels:
      deck-chores.dump.command: sh -c "mysqldump --all-databases > /dumps/dump-$$(date -Idate)"
      deck-chores.dump.interval: daily

“经典”,cron一样的配置也是可能的。

这是文档,这是图像存储库。

在生产环境中,公认的答案可能是危险的。

在docker中,你应该每个容器只执行一个进程,因为如果你不这样做,fork和后台进程就不会被监控,可能会在你不知道的情况下停止。

当你使用CMD cron && tail -f /var/log/cron.log时,cron进程基本上会分叉,以便在后台执行cron,主进程退出,让你在前台执行tailf。后台cron进程可能会停止或失败,但你不会注意到,你的容器仍然会默默地运行,你的编排工具也不会重新启动它。

你可以通过直接将cron的命令输出重定向到分别位于/proc/1/fd/1和/proc/1/fd/2的docker stdout和stderr中来避免这样的事情

使用基本的shell重定向,你可能想做这样的事情:

* * * * * root echo hello > /proc/1/fd/1 2>/proc/1/fd/2

你的CMD将是:CMD ["cron", "-f"]

但是:如果你想以非根用户的身份运行任务,这就行不通了。

我决定使用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日志中看到。

我根据其他答案创建了一个Docker映像,可以像这样使用

docker run -v "/path/to/cron:/etc/cron.d/crontab" gaafar/cron

/path/to/cron: crontab文件的绝对路径,或者你可以在Dockerfile中使用它作为基础文件:

FROM gaafar/cron

# COPY crontab file in the cron directory
COPY crontab /etc/cron.d/crontab

# Add your commands here

作为参考,图片在这里。

在专用容器中定义cronjob,该容器通过docker exec向服务运行命令。

这是更高的内聚性,运行脚本将能够访问为服务定义的环境变量。

#docker-compose.yml
version: "3.3"
services:
    myservice:
      environment:
        MSG: i'm being cronjobbed, every minute!
      image: alpine
      container_name: myservice
      command: tail -f /dev/null

    cronjobber:
     image: docker:edge
     volumes:
      - /var/run/docker.sock:/var/run/docker.sock
     container_name: cronjobber
     command: >
          sh -c "
          echo '* * * * * docker exec myservice printenv | grep MSG' > /etc/crontabs/root
          && crond -f"