Docker cron定时任务

22.1k 技术, 服务器 , 8评论

Docker在部署WEB环境时非常好用,一键即可完整部署,还不受限于具体的主机系统。

不过在使用cron定时,主机运行好好的,到了docker容器中却遇到各式各样的问题。

到底如何在容器中启用cron?

在主机和在容器中使用cron,那种更好?

这里我们列出集中用于定时的方案:

  1. 使用主机的cron实现定时任务
  2. 创建一个新容器专门执行定时任务
  3. 在原有容器上安装cron,里面运行2个进程

注意,我们这里所说的cron,包括传统的 cron 工具,或者其他的时间服务程序,它们功能是一样的。

方式1:最佳

我觉得最佳的方式应该是方式1,因为它最为简单。

比如,我在使用 Docker 搭建的一键 LNMP 环境(http://garymeng.com/2120.html)中,

会定时执行 Nginx 容器中的Certbo命令,以更新 HTTPS/SSL 证书的:

certbot renew

如果在主机中执行(dnmp_nginx_1是容器的名称):

docker exec -it dnmp_nginx_1 certbot renew

那在主机中的crontab -e中就可以:

0 2 * */2 * docker exec dnmp_nginx_1 certbot renew     # 每隔两个月的凌晨2点执行更新

注意:这里docker命令不需要加-it,因为加-it就要开启了一个终端,而计划任务是无法进入任何终端。(感谢小陈留言指正)

这就实现了主机通过docker命令定时执行容器内命令。

如果定时失败,可以开启cron日志看问题所在,方法请看本文末。

方式2

如果由于某种原因,不能使用方式1,那就退而求其次,使用方式2

方式2有一些现成的方案可以使用:https://hub.docker.com/r/willfarrell/crontab

因为这种方式略重,而且必须要同步cron脚本,

方式3

这里我们不讨论选项3,因为从docker的原则上来看,选项3本身就不是个好的方式

开启cron日志

如果定时失败,可以打开cron日志,方法:

sudo vim /etc/rsyslog.d/50-default.conf

将cron前面的注释符去掉:

cron.*              /var/log/cron.log

重启rsyslog

sudo service rsyslog restart

过段时间再查看日志:

tail -f /var/log/cron.log

 

参考资料:

  1. Docker Tip #40: Running Cron Jobs on the Host vs. in a Container
  2. How to run a cron job inside a docker container?

8 条评论

b
buff says: 回复

你好,博主感谢你写的这些博客,我学到了许多.曾经从10点看你博客到深夜4点.近期看到你的github点赞了一个全国行政区域的仓库,我看了一下他那个不怎么全.我自己在自学的时候搞到了一份2017版的全国行政区域共有4万多条记录.望对你有用.
https://github.com/buffge/loadCitys

歪麦 says: 作者

厉害:)

小陈 says: 回复

博主,方法一是否成功执行了?我这边目前遇到问题,手动执行脚本可以的,但是放在crontab里面就执行不成功

小陈 says: 回复

博主,我找到原因了,0 2 * */2 * docker exec -it dnmp_nginx_1 certbot renew 这个里面不能有 -it, exec 加了 -it 参数就开启了一个终端,计划任务是无法进入任何终端的,所以应该是
0 2 * */2 * docker exec dnmp_nginx_1 certbot renew

歪麦 says: 作者

原来这样,多谢指正!

欠谁一世承诺 says: 回复

我在dockerfile中安装了cron,然后在docker-compose里面通过foreman,来启动多个进程,但是好像cron就启动不了哎,能帮忙看下嘛

哈利路亚 says: 回复

* * * * * docker exec CONTAINER_NAME COMMAND >> /test.txt
/test.txt给777的权限

w
willem says: 回复

我用的是win10跑的docker 这个定时方案1应该怎么弄 ?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

昵称 *