Docker 运行时的容器环境变量文件
Docker container environment variable file during runtime
我有一个 docker 图像,它基本上按照使用下面构建图像时定义的频率安排 cron 作业。
COPY myjobtime /etc/cron.d/myjobtime
RUN chmod 0644 /etc/cron.d/myjobtime &&\
crontab /etc/cron.d/myjobtime
CMD cron
我在文件 myjobtime 中有 cron 条目。
*/10 * * * * /usr/local/bin/sh /app/myscript.py
我希望能够在运行时通过 cron 计划。这意味着,如果有人想将 cron 计划修改为不同的频率,他们应该能够在 运行 容器并传递一个包含新 cron 计划的环境变量文件时这样做。这能做到吗?
重要的细节是您需要在容器启动时创建并安装crontab 文件。我发现一个入口点包装器脚本是一个有用的模式:将图像的 ENTRYPOINT
设置为一个 shell 脚本,它可以执行任何需要的 first-time 设置,然后让它 exec "$@"
到 运行 图像的 CMD
。
如果您的映像最终是基于基于 GNU 工具集的 Linux 发行版,那么 envsubst 在这里是一个非常有用的程序。它读入一个文本文件,扩展环境变量引用,然后写出结果。我假设你有这个可用;在 Alpine-based 图像上,您可以使用 sed(1) 执行类似的技巧(尽管绕过 cron 计划会变得棘手)。
这使得入口点包装器脚本类似于:
#!/bin/sh
# entrypoint.sh
# Set a default schedule, if the user didn't provide one
if [ -z "$CRON_SCHEDULE" ]; then
export CRON_SCHEDULE='*/10 * * * *'
fi
# Run substitutions on the template file and inject the crontab
envsubst < /app/myjobtime.cron.tmpl | crontab
# Run the main container command
exec "$@"
由于模板不是“普通”crontab,它不能进入“普通”crontab 目录;放在application目录下就好了。该文件有一个环境变量引用,计划将去哪里
# myjobtime.cron.tmpl
${CRON_SCHEDULE} /app/myscript.py
在您的图像中,将包装器脚本设置为 ENTRYPOINT
,确保模板文件位于正确的位置,并保持 CMD
不变。
# (assuming there's not a broad `COPY . .`)
COPY myjobtime.cron.tmpl .
COPY entrypoint.sh .
ENTRYPOINT ["/app/entrypoint.sh"] # must be JSON-array syntax
CMD cron # unchanged
这应该允许您覆盖 cron 计划。
docker run -d --name hourly myappcron
docker run -d --name daily -e 'CRON_SCHEDULE=0 0 * * *' myappcron
由于入口点包装器脚本 运行 提供了任何命令,并且您可以很容易地覆盖命令,这也让您 double-check 设置了正确的时间表。
docker run --rm -e 'CRON_SCHEDULE=0 0 * * *' myappcron \
crontab -l # runs instead of the cron daemon
我有一个 docker 图像,它基本上按照使用下面构建图像时定义的频率安排 cron 作业。
COPY myjobtime /etc/cron.d/myjobtime
RUN chmod 0644 /etc/cron.d/myjobtime &&\
crontab /etc/cron.d/myjobtime
CMD cron
我在文件 myjobtime 中有 cron 条目。
*/10 * * * * /usr/local/bin/sh /app/myscript.py
我希望能够在运行时通过 cron 计划。这意味着,如果有人想将 cron 计划修改为不同的频率,他们应该能够在 运行 容器并传递一个包含新 cron 计划的环境变量文件时这样做。这能做到吗?
重要的细节是您需要在容器启动时创建并安装crontab 文件。我发现一个入口点包装器脚本是一个有用的模式:将图像的 ENTRYPOINT
设置为一个 shell 脚本,它可以执行任何需要的 first-time 设置,然后让它 exec "$@"
到 运行 图像的 CMD
。
如果您的映像最终是基于基于 GNU 工具集的 Linux 发行版,那么 envsubst 在这里是一个非常有用的程序。它读入一个文本文件,扩展环境变量引用,然后写出结果。我假设你有这个可用;在 Alpine-based 图像上,您可以使用 sed(1) 执行类似的技巧(尽管绕过 cron 计划会变得棘手)。
这使得入口点包装器脚本类似于:
#!/bin/sh
# entrypoint.sh
# Set a default schedule, if the user didn't provide one
if [ -z "$CRON_SCHEDULE" ]; then
export CRON_SCHEDULE='*/10 * * * *'
fi
# Run substitutions on the template file and inject the crontab
envsubst < /app/myjobtime.cron.tmpl | crontab
# Run the main container command
exec "$@"
由于模板不是“普通”crontab,它不能进入“普通”crontab 目录;放在application目录下就好了。该文件有一个环境变量引用,计划将去哪里
# myjobtime.cron.tmpl
${CRON_SCHEDULE} /app/myscript.py
在您的图像中,将包装器脚本设置为 ENTRYPOINT
,确保模板文件位于正确的位置,并保持 CMD
不变。
# (assuming there's not a broad `COPY . .`)
COPY myjobtime.cron.tmpl .
COPY entrypoint.sh .
ENTRYPOINT ["/app/entrypoint.sh"] # must be JSON-array syntax
CMD cron # unchanged
这应该允许您覆盖 cron 计划。
docker run -d --name hourly myappcron
docker run -d --name daily -e 'CRON_SCHEDULE=0 0 * * *' myappcron
由于入口点包装器脚本 运行 提供了任何命令,并且您可以很容易地覆盖命令,这也让您 double-check 设置了正确的时间表。
docker run --rm -e 'CRON_SCHEDULE=0 0 * * *' myappcron \
crontab -l # runs instead of the cron daemon