如何为 Windows 在 Docker 桌面上设置 cron 作业?

How to set up a cron job on Docker Desktop for Windows?

我正在尝试 运行 在 Docker Desktop for windows 的 selenium 容器中执行 cron 作业。因为我认为我 运行 遇到了几个问题,所以我很难弄清楚哪些细节很重要,所以我会尽量做到全面。

环境:

  1. Docker Windows 的桌面(为了避免行结束问题,我在 Docker 文件中制作了 cron 字符串)
  2. Selenium-Chrome(需要注意的是大多数东西在 seluser 而不是 root 下 运行 这里。我这么说是因为其他一些解决方案因此不起作用)

问题:

我不能 运行 python 我的 cron 作业

我检查过的相关堆栈溢出链接:

有很多,但 是主要的。

例如,此代码段记录到适当显示的日志文件中:

FROM selenium/standalone-chrome

COPY . /home/seluser/

# # install selenium
RUN echo "**** install packages ****" && \
    sudo apt-get update && \
    sudo apt-get install -y cron && \
    echo "**** cleanup ****" && \
    sudo apt-get clean && \
    sudo rm -rf \
    /tmp/* \
    /var/lib/apt/lists/* \
    /var/tmp/*

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

# Setup cron job
RUN echo "* * * * * echo "Hello, World!" >> /home/seluser/cron.log" | sudo crontab

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

但事实并非如此:

FROM selenium/standalone-chrome

COPY . /home/seluser/

# # install selenium
RUN echo "**** install packages ****" && \
    sudo apt-get update && \
    sudo apt-get install -y cron && \
    echo "**** cleanup ****" && \
    sudo apt-get clean && \
    sudo rm -rf \
    /tmp/* \
    /var/lib/apt/lists/* \
    /var/tmp/*

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

# Setup cron job
RUN echo "* * * * * /usr/bin/python3 -c print("Hello world") >> /home/seluser/cron.log" | sudo crontab

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

在您的 RUN 命令中,整个命令和嵌入的 Python 脚本中都有双引号。 shell 消耗了这些引号对,因此 Python 片段中根本没有引号。

您可以通过对任何一对引号使用单引号,或通过反斜杠转义双引号字符串中的双引号来解决此问题。所有这些都有效:

RUN echo "... print(\"Hello world\") ..." | crontab
RUN echo "... print('Hello world') ..." | crontab
# NB: will not expand environment variables inside the string
RUN echo '... print("Hello world") ...' | crontab

带有 echo 的第一种形式似乎有效,因为 echo "Hello world"echo Hello worldecho "Hello" "world" 都打印出相同的字符串;它是一个参数还是两个参数并不重要, echo(1) 本身永远不会看到双引号。但是,在 Python 的情况下,您需要将双引号传递给解释器。

如果您面临这样的挑战,通常最好的方法是将嵌入式脚本分解到一个单独的文件中。

#!/usr/bin/env python3
# greet.py
if __name__ == '__main__':
  print('Hello world')

那么你的 cron 作业就可以 运行 脚本。

RUN echo '* * * * * /home/seluser/greet.py >> /home/seluser/cron.log' | crontab

我在示例中省略了 sudo。在 Docker 文件中,您通常已经 运行 成为 root,或者您可以指定 USER root 切换到 root。 sudo 在脚本中使用起来很棘手,并且往往会导致 Docker.

中不必要和不安全的配置

最终的 Docker 文件可能如下所示:

FROM selenium/standalone-chrome

# Install OS packages _before_ copying any application code in.
# This avoids an expensive reinstallation on rebuild.
RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install --assume-yes --no-install-recommends \
      cron

# Now copy your own code in.  (Rebuilds will start here, if anything
# in the source tree has changed.)
COPY . /home/seluser

# Set up the cron environment.
RUN echo '* * * * * /home/seluser/greet.py >> /home/seluser/cron.log' | crontab \
 && touch /home/seluser/cron.log

# Declare the main container command.  (Actually run the cron daemon;
# don't make the container process be tail(1) with cron being an
# unmonitored side effect.)
CMD ["cron", "-f"]