在docker中运行cron python作业
我希望以分离模式在docker容器中运行python cron作业。我的设置如下: 我的python脚本是test.py在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
#!/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发行版如何为自己的软件包实现这一点
# /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作业时,我遇到的几个问题是:
# 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测试日志
docker build-t测试cron。
docker Run--detach=true--t-logs中的卷--name t-cron test cron
docker run-t-i--t-logs ubuntu:latest/bin/bash
。日志文件位于/var/log
中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