问题描述
有一个关于在Docker容器中安排计划任务的问题。他在一个虚拟机上有一个包含入口点(jar)的Docker镜像。他面临一个困境,不知道如何安排任务来运行这个jar文件。他有两个选项:
1. 如果在虚拟机上运行cron,然后调用docker run命令来生成一个容器,并对jar文件运行不同的任务。问题在于,一旦运行了一个任务,容器就会自动终止,并且第二个任务没有前面运行任务的历史记录。他相信有一种方法可以通过入口点使容器永远运行,但他还没有探索/测试过。
2. 他可以在容器内部安装cron,并通过Dockerfile提供cron。然而,问题在于如何启动容器并保持其运行以运行cron任务?
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
你不需要使用cron。大多数服务器操作系统(如CoreOS、RedHat、CentOS、Ubuntu等)现在都使用systemd,systemd单元文件可以运行你的容器来执行任务。以下是一个示例:
1. 创建两个单元文件:mytimedstuff.service和mytimedstuff.timer。.timer文件定义了服务应该何时执行。
2. 在mytimedstuff.service中,添加以下内容:
[Unit]
Description=Executes mystuff
After=default.target docker_network_apps.service
Requires=default.target docker_network_apps.service
[Service]
Type=oneshot
User=root
ExecStartPre=/usr/bin/docker pull mystuff:stable
ExecStartPre=-/bin/bash -c "/usr/bin/docker rm -f mystuffcontainer 2>/dev/null"
ExecStart=/bin/bash -c "/usr/bin/docker run --name mystuffcontainer mystuff:stable mystuff"
- 在mytimedstuff.timer中,添加以下内容:
[Unit]
Description=My stuff runs at 00:10 sharp.
[Timer]
OnCalendar=00:10:00
[Install]
WantedBy=multi-user.target
在上面的示例中,我们定义了两个单元文件:mytimedstuff.service和mytimedstuff.timer。mytimedstuff.service文件定义了容器的启动和停止命令,mytimedstuff.timer文件定义了服务应该在何时执行。你可以根据自己的需求修改这些文件。
方案2
在Docker中,最佳实践是为不同的进程创建多个容器,并通过docker-compose管理它们。这样可以在一个文件中定义应用程序所需的所有容器,并通过一个命令启动它们。
另一种方法是使用ENTRYPOINT
来运行一个管理进程的脚本,或者使用像supervisord
这样的进程管理器。以下是两种简单的解决方案:
1. 使用ENTRYPOINT
运行一个脚本来管理多个进程。你可以在Docker文档中找到一个示例。
2. 使用进程管理器supervisord
,你可以在这篇文章中找到关于如何在Docker中使用supervisor的详细说明。
需要注意的是,在使用Docker时,一个容器只应该运行一个服务。
总结
在本文中,我们讨论了如何在Docker容器中安排计划任务。我们提供了两种解决方案:使用systemd单元文件或使用进程管理器。你可以根据自己的需求选择适合你的解决方案。
请注意,这些解决方案可能会因版本差异而有所不同。在实施之前,请确保备份你的数据并仔细阅读相关文档。
希望这些解决方案对你有帮助!如果你有任何进一步的问题,请随时提问。