Cron containers for docker - how do they actually

2019-02-16 22:35发布

问题:

I have been using docker for a couple of months now, and am working on dockerizing various different server images. One consistent issue is that many servers need to run cron jobs. There is a lot of discussion about that online (including on Stackoverflow), but I don't completely understand the mechanics of it.

Currently, I am using the host's cron and docker exec into each container to run a script. I created a convention about the script's name and location; all my containers have the same script. This avoids having the host's cron depending on the containers.

Basically, once a minute, the host's cron does this:

for each container
   docker exec -it <containername> /cronscript/minute-script

That works, but makes the containers depend on the host.

What I would like to do is create a cron container that kicks off a script within each of the other containers - but I am not aware of an equivalent to "docker exec" that works from one container to the other.

The specific situations I have right now are running a backup in a MySQL container, and running the cron jobs Moodle requires to be run every minute. Eventually, there will be additional things I need to do via cron. Moodle uses command-line PHP scripts.

What is the "proper" dockerized way to kick off a script from one container in another container?

Update: maybe it helps to mention my specific use cases, although there will be more as time goes on.

Currently, cron needs to do the following:

  • Perform a database dump from MySQL. I can do that via mysqldump TCP link from a cron container; the drawback here is that I can't limit the backup user to host 127.0.0.1. I might also be able to somehow finagle the MySQL socket into the cron container via a volume.
  • Perform regular maintenance on a Moodle installation. Moodle includes a php command line script that runs all of the maintenance tasks. This is the biggie for me. I can probably run this script through a volume, but Moodle was not designed with that situation in mind, and I would not rule out race conditions. Also, I do not want my moodle installation in a volume because it makes updating the container much harder (remember that in Docker, volumes are not reinitialized when you update the container with a new image).
  • Future: perform routine maintenance on a number of other of my servers, such as cleaning out email queues, etc.

回答1:

My solution is:

  • install crond inside container
  • install Your soft
  • run cron as a daemon
  • run Your soft

Part of my Dockerfile

FROM debian:jessie

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY .crontab /usr/src/app

# Set timezone
RUN echo "Europe/Warsaw" > /etc/timezone \
    && dpkg-reconfigure --frontend noninteractive tzdata

# Cron, mail
RUN set -x \
    && apt-get update \
    && apt-get install -y cron rsyslog mailutils --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

CMD rsyslogd && env > /tmp/crontab && cat .crontab >> /tmp/crontab && crontab /tmp/crontab && cron -f

Description

  1. Set timezone, because cron need this to proper run tasks
  2. Install cron package - package with cron daemon
  3. Install rsyslog package to log cron task output
  4. Install mailutils package if You want to send e-mails from cron tasks
  5. Run rsyslogd
  6. Copy ENV variables to tmp file, because cron run tasks with minimal ENV and You tasks may need access to containers ENV variables
  7. Append Your .crontab file (with Your tasks) to tmp file
  8. Set root crontab from tmp file
  9. Run cron daemon

I use this in my containers and work very well.

one-process-per-container

If You like this paradigm, then make one Dockerfile per cron task. e.g.

  • Dockerfile - main program
  • Dockerfile_cron_task_1 - cron task 1
  • Dockerfile_cron_task_1 - cron task 2

and build all containers:

docker build -f Dockerfile_cron_task_1 ...


标签: cron docker