尝试使用 crontab 和简单的 python 脚本运行一个简单的 docker 容器

ge0*_*rge 0 cron containers docker dockerfile

所以我对创建容器还很陌生,我有一个简单的 Dockerfile,我想在其中每分钟运行一个简单的 python 脚本:

FROM python:3.8-buster
RUN apt-get update && apt-get install -y cron
COPY my_python /bin/my_python
COPY root /var/spool/cron/crontabs/root
RUN chmod +x /bin/my_python
CMD cron -l 2 -f
Run Code Online (Sandbox Code Playgroud)

其中我的_python:

print("hi world!!")
Run Code Online (Sandbox Code Playgroud)

和根:

* * * * * python3 /bin/my_python
Run Code Online (Sandbox Code Playgroud)

然后我只创建图像和容器:

 docker image build -t python-test
 docker container run -it --name python-test python-test
Run Code Online (Sandbox Code Playgroud)

我应该每分钟都会看到一个带有 hi world 的打印,但是当运行容器时(在图像构建之后)似乎没有出现日志。

我究竟做错了什么?

lar*_*sks 5

首先,我相信你想要的-L 2不是-l 2cron命令行中;有关详细信息,请参阅手册页

守护进程cron会记录到系统日志中,因此,如果某些内容未按预期工作,最好安排接收这些消息。该busybox工具提供了一个简单的系统日志守护进程,可以记录到内存缓冲区和一个用于读取这些日志的工具,因此我将其修改Dockerfile为如下所示:

FROM python:3.8-buster
RUN apt-get update && apt-get install -y cron busybox
COPY my_python /bin/my_python
COPY root /var/spool/cron/crontabs/root
RUN chmod +x /bin/my_python
CMD busybox syslogd -C; cron -L 2 -f
Run Code Online (Sandbox Code Playgroud)

开始之后,我docker exec进入容器并运行busybox logread并发现:

Jan 24 16:50:45 7f516db86417 cron.info cron[4]: (CRON) INFO (pidfile fd = 3)
Jan 24 16:50:45 7f516db86417 cron.info cron[4]: (root) INSECURE MODE (mode 0600 expected) (crontabs/root)
Jan 24 16:50:45 7f516db86417 cron.info cron[4]: (CRON) INFO (Running @reboot jobs)
Run Code Online (Sandbox Code Playgroud)

所以这就是你的问题:crontab 上的权限root不正确。有两种方法可以解决此问题:

  1. chmod当我们将文件复制到位时,我们可以明确地指定该文件,或者
  2. 我们可以使用crontab命令来安装该文件,它会为我们解决这个问题

我喜欢选项 2,因为这意味着我们不需要了解cron权限方面的具体细节。这让我们:

FROM python:3.8-buster
RUN apt-get update && apt-get install -y cron busybox
COPY my_python /bin/my_python
COPY root /tmp/root.crontab
RUN crontab /tmp/root.crontab
RUN chmod +x /bin/my_python
CMD busybox syslogd -C; cron -L 2 -f
Run Code Online (Sandbox Code Playgroud)

通过这一更改,我们可以确认 cron 作业现在正在按预期运行:

Jan 24 16:59:50 8aa688ad31cc syslog.info syslogd started: BusyBox v1.30.1
Jan 24 16:59:50 8aa688ad31cc cron.info cron[4]: (CRON) INFO (pidfile fd = 3)
Jan 24 16:59:50 8aa688ad31cc cron.info cron[4]: (CRON) INFO (Running @reboot jobs)
Jan 24 17:00:01 8aa688ad31cc authpriv.err CRON[7]: pam_env(cron:session): Unable to open env file: /etc/default/locale: No such file or directory
Jan 24 17:00:01 8aa688ad31cc authpriv.info CRON[7]: pam_unix(cron:session): session opened for user root by (uid=0)
Jan 24 17:00:02 8aa688ad31cc cron.info CRON[7]: (root) END (python3 /bin/my_python)
Jan 24 17:00:02 8aa688ad31cc authpriv.info CRON[7]: pam_unix(cron:session): session closed for user root
Run Code Online (Sandbox Code Playgroud)

但是......容器仍然没有输出!如果您仔细阅读该手册页,您会发现:

然后 cron 每分钟醒来,检查所有存储的 crontab,检查每个命令以查看它是否应该在当前分钟运行。执行命令时,任何输出都会邮寄给 crontab 的所有者(或者发送给 crontab 中 MAILTO 环境变量中指定的用户,如果存在的话)...

换句话说,cron收集程序的输出并尝试通过邮件发送给拥有 cron 作业的用户。如果您想在控制台上查看作业的输出cron,则需要显式重定向 stdout,如下所示:

* * * * * python3 /bin/my_python > /dev/console
Run Code Online (Sandbox Code Playgroud)

完成此更改后,运行图像会产生消息...

hi world!
Run Code Online (Sandbox Code Playgroud)

...每分钟打印到控制台一次。