最近弄了一个数据库自动备份的脚本,打算在docker容器中使用它,过程一直很顺利,直到在设置定时任务时,跳进了docker容器埋藏的大坑。不知道官方是处于什么样的考虑,在mariadb这个镜像中竟然移除了cron这个定时服务,导致只能手动安装。
所以:

  • 我们在 Dockefiles 里面首先要安装 cron:apt-get install -y cron
  • 执行任务的脚本需要写入:echo "*/1 * * * * ./backup_db.sh" >> /etc/crontab
  • 启动 cron 的自启动:update-rc.d cron defaults 99

但是,这个 update-rc.d 并没有生效!!

尝试让容器自启动服务

找了很久,找到一个原因:http://jpetazzo.github.io/2013/10/06/policy-rc-d-do-not-start-services-automatically/
大致是说,在执行 update-rc.d 任务的时候,会先运行一下/usr/sbin/policy-rc.d 任务(如果有)。
如果返回值是 0,那么 OK,执行任务,如果返回值是 101,那么不好意思,任务不执行。
事实上 Docker 在容器里面就直接返回了个 101,所以执行update-rc.d的时候根本没用。
为了放行服务的自启动,可以在dockerfile文件中添加以下命令:

RUN rm -rf /usr/sbin/policy-rc.d
RUN echo $'#!/bin/sh\nexit 0' >> /usr/sbin/policy-rc.d
RUN chmod +x /usr/sbin/policy-rc.d
RUN update-rc.d cron defaults 99

但是,这个并没有什么用!!!
进入到容器环境中,执行service cron status依然是冷冰冰的提示:cron is not running

使用docker-composecommand命令来启动服务

在万般无奈下,想到了使用docker-composecommand来启动代码,于是在command中编写来以下命令:

command:
bash -c "service cron start

终于算是看到了cron是成功启动了,这时容器却无法启动了,查看日志,说是mysqld服务没有启动,what????

由于command但特殊性,猜测应该是bash -c "service cron start"覆盖容器默认的启动命令,导致mysqld服务没有启动。
于是在docker-compose中去掉command命令,正确创建容器,然后使用dcoker inspect 查看容器的属性。

果然,mariadb容器有一个默认的启动命令:docker-entrypostion.sh mysqld
重新修改command命令为:

command:
bash -c "service cron start && /usr/local/bin/docker-entrypoint.sh mysqld"


终于看到,cronmysqld服务都正常执行了。。。

进入容器,查看cron状态,终于一切都正常了,不容易啊!!