While is perfectly possible to use cron inside a container, I strongly advise you to don’t do it. Some of the most important points on why is a bad practice to run cron inside a container:
Your tasks need to be ephemeral as your containers
We live in the immutable infrastructure era, there is no need to worry about
cleaning up everything before or after your tasks run. Make your scheduled tasks
ephemeral as your containers, if something goes wrong, you can inspect the
precise state that the container was left. Even with Tasker supporting reusing
reuse: true) this is not recommended.
Let your tasks be ephemeral as possible, you can always count on a clean environment for every execution.
Maintain custom images is time consuming
With Tasker, you simply use the images that are already available, no more extra work required.
No alerts when tasks fail
Cron doesn’t provide anything out of the box to alert about your tasks execution status. Tasker in the other hand come with batteries included and ships alerting out of the box, here the official docs.
Is hard to keep everything as code
Considering the first scenario, with 3 tasks each one with a image for each. If you keep the good practices, you will create a git repository for each one, with their own build. It means that you have 3 additional repositories to keep track of.
With Tasker you can simply have one configuration file and replace all those repositories with one repository.
Introduction to Tasker
Tasker is a task scheduler and runner, it works by creating containers on demand
to run your task.
Let’s use a practical example, considering the
docker-compose.yml file bellow:
version: "3" services: tasker: image: strm/tasker volumes: - "/var/run/docker.sock:/var/run/docker.sock" environment: configuration: | schedule: - every: minute task: hello tasks: docker: - name: hello image: debian:jessie script: - echo Hello world from Tasker
Tasker can be configured in several ways, one way is setting the environment
configuration and set it to your yml configuration. As you can notice,
it goes really well with the docker-compose file.
Let’s break down the configuration to explain what is going on. We can break it
in two main sections,
schedule and `tasks**.
Schedules are the triggers to our tasks, they are defined as an array of
schedule. These schedules are defined by two main properties, when they will
trigger the task, and what tasks they will trigger.
Another good point of Tasker is that you don’t have to memorize some abstract
cron syntax, it uses a more human language, like in this example
it means every 1 minute this task will run. Test it, change to
every: 10 minutes
and observe the results. You can also set it as a default cron syntax.
More about scheduling can be found on the official docs
The second element of the configuration (and the most important) are the tasks,
tasks defined under the
docker property represent a docker container
definitions, they reflect the container that will be created when triggered and
will execute your commands. You can use any docker image to run your commands
Here a more elaborate example to illustrate how you can use several images on the same configuration
version: "3" services: tasker: image: strm/tasker volumes: - "/var/run/docker.sock:/var/run/docker.sock" environment: configuration: | logging: level: ROOT: WARN org.springframework.web: WARN sh.strm: DEBUG schedule: - every: minute task: hello - every: minute task: helloFromPython - every: minute task: helloFromNode tasks: docker: - name: hello image: debian:jessie script: - echo Hello world from Tasker - name: helloFromPython image: python:3-slim script: - python -c 'print("Hello world from python")' - name: helloFromNode image: node:8 script: - node -e 'console.log("Hello from node")'
Note that in this example, we have only one source file, but if you had to replicate it using cron you would had to create 3 images, one for each base image + the cron daemon, and, or map your scripts to it, or copy it on the build. After a while the maintenance required to keep everything updated will consume a significant amount of time. This is one of the main scenarios where Tasker simplifies a lot the work required.
Basically everything that you need to configure in a container, from networking, volumes, and everything else can be done using this configuration section, for more info see the official docs.