Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在docker中运行cron python作业_Python_Cron_Docker - Fatal编程技术网

在docker中运行cron python作业

在docker中运行cron python作业,python,cron,docker,Python,Cron,Docker,我希望以分离模式在docker容器中运行python cron作业。我的设置如下: 我的python脚本是test.py #!/usr/bin/env python import datetime print "Cron job has run at %s" %datetime.datetime.now() 我的cron文件是我的crontab * * * * * /test.py > /dev/console 我的Dockerfile是 FROM ubuntu:l

我希望以分离模式在docker容器中运行python cron作业。我的设置如下:

我的python脚本是test.py

#!/usr/bin/env python
import datetime
print "Cron job has run at %s" %datetime.datetime.now()
我的cron文件是我的crontab

* * * * * /test.py > /dev/console
我的Dockerfile是

FROM ubuntu:latest
RUN apt-get update && apt-get install -y software-properties-common python-software-properties && apt-get update

RUN apt-get install -y python cron
ADD my-crontab /
ADD test.py /
RUN chmod a+x test.py

RUN crontab /my-crontab
ENTRYPOINT cron -f

这种方法的潜在问题是什么?还有其他方法吗?它们的优缺点是什么?

/etc/cron.d/
中添加crontab片段而不是使用root的
crontab
可能更可取

这将:

  • 通过将其他cron作业添加到该文件夹,可以添加这些作业
  • 为您节省几层
  • 模拟Debian发行版如何为自己的软件包实现这一点
请注意,这些文件的格式与crontab条目略有不同。以下是Debian php包中的一个示例:

# /etc/cron.d/php5: crontab fragment for php5
#  This purges session files older than X, where X is defined in seconds
#  as the largest value of session.gc_maxlifetime from all your php.ini
#  files, or 24 minutes if not defined.  See /usr/lib/php5/maxlifetime

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && [ -x /usr/lib/php5/sessionclean ] && [ -d /var/lib/php5 ] && /usr/lib/php5/sessionclean /var/lib/php5 $(/usr/lib/php5/maxlifetime)

总的来说,根据经验,在容器中运行cron确实工作得很好(除了cron日志记录之外,还有很多需要改进的地方)

在docker容器中运行cron作业时,我遇到的几个问题是:

  • docker容器中的时间是UTC而不是本地时间
  • docker环境未传递给cron
  • 正如Thomas所指出的,cron日志记录还有很多需要改进的地方,通过docker访问它需要基于docker的解决方案
  • 列表中有特定于cron的问题和特定于docker的问题,但在任何情况下都必须解决这些问题才能使cron正常工作

    为此,我目前对该问题提出的问题的工作解决办法如下:

    # BUILD-USING:        docker build -t test-cron .
    # RUN-USING docker run --detach=true --volumes-from t-logs --name t-cron test-cron
    
    FROM debian:wheezy
    #
    # Set correct environment variables.
    ENV HOME /root
    ENV TEST_ENV test-value
    
    RUN apt-get update && apt-get install -y software-properties-common python-software-properties && apt-get update
    
    # Install Python Setuptools
    RUN apt-get install -y python cron
    
    RUN apt-get purge -y python-software-properties software-properties-common && apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
    
    ADD cron-python /etc/cron.d/
    ADD test.py /
    ADD run-cron.py /
    
    RUN chmod a+x test.py run-cron.py
    
    # Set the time zone to the local time zone
    RUN echo "America/New_York" > /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata
    
    CMD ["/run-cron.py"]
    
    创建一个docker卷,在cron下运行的所有脚本都将写入该卷:

    # Dockerfile for test-logs
    
    # BUILD-USING:        docker build -t test-logs .
    # RUN-USING:          docker run  -d -v /t-logs --name t-logs test-logs
    # INSPECT-USING:      docker run -t -i  --volumes-from t-logs ubuntu:latest /bin/bash
    
    FROM stackbrew/busybox:latest
    
    # Create logs volume
    VOLUME /var/log
    
    CMD  ["true"]
    
    将在cron下运行的脚本是
    test.py

    #!/usr/bin/env python
    
    # python script which needs an environment variable and runs as a cron job
    import datetime
    import os
    
    test_environ = os.environ["TEST_ENV"]
    print "Cron job has run at %s with environment variable '%s'" %(datetime.datetime.now(), test_environ)
    
    为了将环境变量传递给我想要在cron下运行的脚本,请按照Thomas的建议,在
    /etc/cron.d
    中为需要docker环境变量的每个脚本(或脚本组)放置一个crontab片段,并带有一个必须设置的占位符
    XXXXXXX

    # placed in /etc/cron.d 
    # TEST_ENV is an docker environment variable that the script test.py need
    
    TEST_ENV=XXXXXXX
    #
    * * * * * root python /test.py >> /var/log/test.log
    
    不要直接调用cron,而是将cron封装在一个python脚本中,该脚本可以执行以下操作:1。从docker环境变量读取环境变量,并在crontab片段中设置环境变量

    #!/usr/bin/env python
    
    # run-cron.py
    # sets environment variable crontab fragments and runs cron
    
    import os
    from subprocess import call
    import fileinput
    
    # read docker environment variables and set them in the appropriate crontab fragment
    environment_variable = os.environ["TEST_ENV"]
    
    for line in fileinput.input("/etc/cron.d/cron-python",inplace=1):
        print line.replace("XXXXXXX", environment_variable)
    
    args = ["cron","-f", "-L 15"]
    call(args)
    
    运行cron作业的容器的
    Dockerfile
    如下所示:

    # BUILD-USING:        docker build -t test-cron .
    # RUN-USING docker run --detach=true --volumes-from t-logs --name t-cron test-cron
    
    FROM debian:wheezy
    #
    # Set correct environment variables.
    ENV HOME /root
    ENV TEST_ENV test-value
    
    RUN apt-get update && apt-get install -y software-properties-common python-software-properties && apt-get update
    
    # Install Python Setuptools
    RUN apt-get install -y python cron
    
    RUN apt-get purge -y python-software-properties software-properties-common && apt-get clean -y && apt-get autoclean -y && apt-get autoremove -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
    
    ADD cron-python /etc/cron.d/
    ADD test.py /
    ADD run-cron.py /
    
    RUN chmod a+x test.py run-cron.py
    
    # Set the time zone to the local time zone
    RUN echo "America/New_York" > /etc/timezone && dpkg-reconfigure --frontend noninteractive tzdata
    
    CMD ["/run-cron.py"]
    
    最后,创建容器并运行它们:

  • 创建日志卷(测试日志)容器:
    docker build-t测试日志。
  • 运行日志卷:
    docker Run-d-v/t-logs——名称t-logs测试日志
  • 创建cron容器:
    docker build-t测试cron。
  • 运行cron容器:
    docker Run--detach=true--t-logs中的卷--name t-cron test cron
  • 要检查在cron下运行的脚本的日志文件,请执行以下操作:
    docker run-t-i--t-logs ubuntu:latest/bin/bash
    。日志文件位于
    /var/log
  • 单容器法 您可以在使用能够很好地处理PID 0的基本映像的同一容器中运行
    crond
    ,如

    专用容器法 更干净的方法可能是将另一个容器链接到它,而该容器只运行
    crond
    。例如:

    Dockerfile

     FROM busybox
     ADD crontab /var/spool/cron/crontabs/www-data
     CMD crond -f
    
    ADD docker/cron/my-cron /etc/cron.d/my-cron
    RUN chmod 0644 /etc/cron.d/my-cron
    
    ADD docker/cron/entrypoint.sh /etc/entrypoint.sh
    
    ENTRYPOINT ["/bin/sh", "/etc/entrypoint.sh"]
    
    crontab

     * * * * * echo $USER
    
    然后运行:

     $ docker build -t cron .
     $ docker run --rm --link something cron
    

    注意:在这种情况下,它将作为
    www-data
    运行作业。不能将
    crontab
    文件作为卷装载,因为它需要由
    root
    拥有,并且只有
    root
    的写访问权限,否则
    crond
    将不运行任何操作。此外,您还必须以
    root
    的身份运行
    crond
    ,这是对rosksw答案的补充

    为了将环境变量传递给cron作业,不需要在crontab文件中进行字符串替换

    在运行container时,将环境变量存储在一个文件中,然后在每次cron执行时从该文件加载它们,这样做更简单。我找到了小费

    在dockerfile中:

    CMD mkdir -p /data/log && env > /root/env.txt && crond -n
    
    在crontab文件中:

    * * * * * root env - `cat /root/env.txt` my-script.sh
    

    另一种可能性是使用。Crython允许您在单个python脚本/进程中定期调度python函数。它甚至可以理解cron语法:

    @crython.job(expr='0 0 0 * * 0 *')
    def job():
        print "Hello world"
    

    使用crython避免了在docker容器中运行crond的各种麻烦-您的作业现在是一个单独的进程,需要时可以唤醒,这更适合docker执行模型。但它的缺点是将日程安排放在程序中,这并不总是可取的。不过,它在某些用例中可能很方便。

    这里有一个替代解决方案

    Dockerfile

     FROM busybox
     ADD crontab /var/spool/cron/crontabs/www-data
     CMD crond -f
    
    ADD docker/cron/my-cron /etc/cron.d/my-cron
    RUN chmod 0644 /etc/cron.d/my-cron
    
    ADD docker/cron/entrypoint.sh /etc/entrypoint.sh
    
    ENTRYPOINT ["/bin/sh", "/etc/entrypoint.sh"]
    
    entrypoint.sh中

     #!/usr/bin/env bash
      printenv | cat - /etc/cron.d/my-cron > ~/my-cron.tmp \
        && mv ~/my-cron.tmp /etc/cron.d/my-cron
    
    cron -f
    

    我们正在使用下面的解决方案。它支持
    docker日志
    功能和在PID 1上的容器中挂起cron进程的能力(如果您使用上面提供的
    tail-f
    解决方法-如果cron崩溃,docker将不遵循重启策略):

    cron.sh:

    #!/usr/bin/env bash
    
    printenv | cat - /etc/cron.d/cron-jobs > ~/crontab.tmp \
        && mv ~/crontab.tmp /etc/cron.d/cron-jobs
    
    chmod 644 /etc/cron.d/cron-jobs
    
    tail -f /var/log/cron.log &
    
    cron -f
    
    RUN apt-get install --no-install-recommends -y -q cron 
    
    ADD cron.sh /usr/bin/cron.sh
    RUN chmod +x /usr/bin/cron.sh
    
    ADD ./crontab /etc/cron.d/cron-jobs
    RUN chmod 0644 /etc/cron.d/cron-jobs
    
    RUN touch /var/log/cron.log
    
    ENTRYPOINT ["/bin/sh", "/usr/bin/cron.sh"]
    
    * * * * * root <cmd> >> /var/log/cron.log 2>&1
    
    Dockerfile:

    #!/usr/bin/env bash
    
    printenv | cat - /etc/cron.d/cron-jobs > ~/crontab.tmp \
        && mv ~/crontab.tmp /etc/cron.d/cron-jobs
    
    chmod 644 /etc/cron.d/cron-jobs
    
    tail -f /var/log/cron.log &
    
    cron -f
    
    RUN apt-get install --no-install-recommends -y -q cron 
    
    ADD cron.sh /usr/bin/cron.sh
    RUN chmod +x /usr/bin/cron.sh
    
    ADD ./crontab /etc/cron.d/cron-jobs
    RUN chmod 0644 /etc/cron.d/cron-jobs
    
    RUN touch /var/log/cron.log
    
    ENTRYPOINT ["/bin/sh", "/usr/bin/cron.sh"]
    
    * * * * * root <cmd> >> /var/log/cron.log 2>&1
    
    crontab:

    #!/usr/bin/env bash
    
    printenv | cat - /etc/cron.d/cron-jobs > ~/crontab.tmp \
        && mv ~/crontab.tmp /etc/cron.d/cron-jobs
    
    chmod 644 /etc/cron.d/cron-jobs
    
    tail -f /var/log/cron.log &
    
    cron -f
    
    RUN apt-get install --no-install-recommends -y -q cron 
    
    ADD cron.sh /usr/bin/cron.sh
    RUN chmod +x /usr/bin/cron.sh
    
    ADD ./crontab /etc/cron.d/cron-jobs
    RUN chmod 0644 /etc/cron.d/cron-jobs
    
    RUN touch /var/log/cron.log
    
    ENTRYPOINT ["/bin/sh", "/usr/bin/cron.sh"]
    
    * * * * * root <cmd> >> /var/log/cron.log 2>&1
    
    ***root>>/var/log/cron.log 2>&1
    

    请别忘了在你的crontab中添加令人毛骨悚然的新行

    不要把crond和你的基本图像混在一起。更愿意为您的语言使用本机解决方案(如Anton所说的schedule或crython),或者将其解耦。通过解耦,我的意思是,保持事物的分离,这样您就不必维护一个映像,而只是作为python和crond之间的融合

    如果您想保持事情的解耦,可以使用一个具有cron(调度器)支持的任务运行程序来解决这个问题

    这里有一个
    docker compose.yml
    文件,它将为您运行一些任务

    version: "2"
    
    services:
        tasker:
            image: strm/tasker
            volumes:
                - "/var/run/docker.sock:/var/run/docker.sock"
            environment:
                configuration: |
                    logging:
                        level:
                            ROOT: WARN
                            org.springframework.web: WARN
                            sh.strm: DEBUG
                    schedule:
                        - every: minute
                          task: helloFromPython
                    tasks:
                        docker:
                            - name: helloFromPython
                              image: python:3-slim
                              script:
                                  - python -c 'print("Hello world from python")'
    
    只需运行
    docker compose up
    ,并查看它的工作情况。以下是Tasker回购协议及其完整文档:


    以下是我在docker中调试cron python脚本的清单:

  • 确保运行
    cron
    命令somew