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

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


当前回答

@VonC的建议很好,但我更喜欢在一行中完成所有cron作业配置。这将避免像cronjob位置这样的跨平台问题,并且您不需要单独的cron文件。

FROM ubuntu:latest

# Install cron
RUN apt-get -y install cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Setup cron job
RUN (crontab -l ; echo "* * * * * echo "Hello world" >> /var/log/cron.log") | crontab

# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

运行docker容器后,你可以通过以下方式确定cron服务是否在工作:

# To check if the job is scheduled
docker exec -ti <your-container-id> bash -c "crontab -l"
# To check if the cron service is running
docker exec -ti <your-container-id> bash -c "pgrep cron"

如果你喜欢用ENTRYPOINT代替CMD,那么你可以用

ENTRYPOINT cron start && tail -f /var/log/cron.log

但是:如果cron死亡,容器将继续运行。

其他回答

不幸的是,上面的答案都不适合我,尽管所有的答案都指向解决方案,并最终指向我的解决方案,如果它对某人有帮助,这里是一个片段。谢谢

这个问题可以用bash文件解决,由于Docker的分层架构,cron服务不会通过RUN/CMD/ENTRYPOINT命令启动。

只需添加一个bash文件,该文件将启动cron和其他服务(如果需要)

DockerFile

FROM gradle:6.5.1-jdk11 AS build
# apt
RUN apt-get update
RUN apt-get -y install cron
# Setup cron to run every minute to print (you can add/update your cron here)
RUN touch /var/log/cron-1.log
RUN (crontab -l ; echo "* * * * * echo testing cron.... >> /var/log/cron-1.log 2>&1") | crontab
# entrypoint.sh
RUN chmod +x entrypoint.sh
CMD ["bash","entrypoint.sh"]

entrypoint.sh

#!/bin/sh
service cron start & tail -f /var/log/cron-2.log

如果任何其他服务也需要与cron一起运行,那么在同一个命令中添加&,例如:/opt/wildfly/bin/standalone.sh & service cron start & tail -f /var/log/cron-2.log

一旦你进入docker容器,你可以看到测试cron....将每分钟打印在文件:/var/log/cron-1.log

但是,如果cron死亡,容器将继续运行。

所以,我的问题也一样。修复方法是改变docker-compose.yml中的命令部分。

From

命令:crontab /etc/crontab && tail -f /etc/crontab

To

命令:crontab /etc/crontab

命令:tail -f /etc/crontab

问题在于命令之间的“&&”。删除后,一切都好了。

所有的答案都需要容器内的根访问权限,因为'cron'本身请求UID 0。 请求根访问(例如通过sudo)是违反docker最佳实践的。 我使用https://github.com/gjcarneiro/yacron来管理计划任务。

如果映像不包含任何守护进程(因此只有短时间运行的脚本或进程),还可以考虑从外部启动cron,只需用cron信息定义一个LABEL,再加上调度器本身。这样,您的默认容器状态是“exited”。如果您有多个脚本,这可能会比拥有多个并行运行的cron实例减少系统占用空间。

参见:https://github.com/JaciBrunning/docker-cron-label

示例docker-compose.yaml:

version: '3.8'

# Example application of the cron image
services:
  cron:
    image: jaci/cron-label:latest
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/etc/localtime:/etc/localtime:ro"

  hello:
    image: hello-world
    restart: "no"
    labels:
      - "cron.schedule=* * * * * "

在专用容器中定义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"