Ofelia is a modern and low footprint job scheduler for docker environments, built on Go. Ofelia aims to be a replacement for the old fashioned cron.
It has been a long time since cron
was released, actually more than 28 years. The world has changed a lot and especially since the Docker
revolution. Vixie's cron works great but it's not extensible and it's hard to debug when something goes wrong.
Many solutions are available: ready to go containerized crons
, wrappers for your commands, etc. but in the end simple tasks become complex.
The main feature of Ofelia is the ability to execute commands directly on Docker containers. Using Docker's API Ofelia emulates the behavior of exec
, being able to run a command inside of a running container. Also you can run the command in a new container destroying it at the end of the execution.
Scheduling format is the same as the Go implementation of cron
. E.g. @every 10s
or 0 0 1 * * *
(every night at 1 AM).
Note: the format starts with seconds, instead of minutes.
you can configure four different kind of jobs:
job-exec
: this job is executed inside of a running container.job-run
: runs a command inside of a new container, using a specific image.job-local
: runs the command inside of the host running ofelia.job-service-run
: runs the command inside a new "run-once" service, for running inside a swarmSee Jobs reference documentation for all available parameters.
Run with ofelia daemon --config=/path/to/config.ini
[job-exec "job-executed-on-running-container"]
schedule = @hourly
container = my-container
command = touch /tmp/example
[job-run "job-executed-on-new-container"]
schedule = @hourly
image = ubuntu:latest
command = touch /tmp/example
[job-local "job-executed-on-current-host"]
schedule = @hourly
command = touch /tmp/example
[job-service-run "service-executed-on-new-container"]
schedule = 0,20,40 * * * *
image = ubuntu
network = swarm_network
command = touch /tmp/example
In order to use this type of configurations, ofelia need access to docker socket.
docker run -it --rm \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--label ofelia.job-local.my-test-job.schedule="@every 5s" \
--label ofelia.job-local.my-test-job.command="date" \
mcuadros/ofelia:latest daemon --docker
Labels format: ofelia.<JOB_TYPE>.<JOB_NAME>.<JOB_PARAMETER>=<PARAMETER_VALUE>
.
This type of configuration supports all the capabilities provided by INI files.
Also, it is possible to configure job-exec
by setting labels configurations on the target container. To do that, additional label ofelia.enabled=true
need to be present on the target container.
For example, we want ofelia
to execute uname -a
command in the existing container called my_nginx
.
To do that, we need to we need to start my_nginx
container with next configurations:
docker run -it --rm \
--label ofelia.enabled=true \
--label ofelia.job-exec.test-exec-job.schedule="@every 5s" \
--label ofelia.job-exec.test-exec-job.command="uname -a" \
nginx
Now if we start ofelia
container with the command provided above, it will pickup 2 jobs:
date
uname -a
Or with docker-compose:
version: "3"
services:
ofelia:
image: mcuadros/ofelia:latest
depends_on:
- nginx
command: daemon --docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
ofelia.job-local.my-test-job.schedule: "@every 5s"
ofelia.job-local.my-test-job.command: "date"
nginx:
image: nginx
labels:
ofelia.enabled: "true"
ofelia.job-exec.datecron.schedule: "@every 5s"
ofelia.job-exec.datecron.command: "uname -a"
Ofelia reads labels of all Docker containers for configuration by default. To apply on a subset of containers only, use the flag --docker-filter
(or -f
) similar to the filtering for docker ps
. E.g. to apply to current docker compose project only using label
filter:
version: "3"
services:
ofelia:
image: mcuadros/ofelia:latest
depends_on:
- nginx
command: daemon --docker -f label=com.docker.compose.project=${COMPOSE_PROJECT_NAME}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
ofelia.job-local.my-test-job.schedule: "@every 5s"
ofelia.job-local.my-test-job.command: "date"
nginx:
image: nginx
labels:
ofelia.enabled: "true"
ofelia.job-exec.datecron.schedule: "@every 5s"
ofelia.job-exec.datecron.command: "uname -a"
Ofelia comes with three different logging drivers:
mail
to send mailssave
to save structured execution reports to a directoryslack
to send messages via a slack webhookThese can be configured by setting the options listed below in the [global]
section of your config.ini, or via docker labels on the ofelia
container (regardless of where your job will actually be running).
smtp-host
- address of the SMTP server.
smtp-port
- port number of the SMTP server.
smtp-user
- user name used to connect to the SMTP server.
smtp-password
- password used to connect to the SMTP server.
smtp-tls-skip-verify
- when true
ignores certificate signed by unknown authority error.
email-to
- mail address of the receiver of the mail.
email-from
- mail address of the sender of the mail.
mail-only-on-error
- only send a mail if the execution was not successful.
save-folder
- directory in which the reports shall be written (must already exist).
save-only-on-error
- only save a report if the execution was not successful.
slack-webhook
- URL of the slack webhook.
slack-only-on-error
- only send a slack message if the execution was not successful.
Ofelia can prevent that a job is run twice in parallel (e.g. if the first execution didn't complete before a second execution was scheduled. If a job has the option no-overlap
set, it will not be run concurrently.
The easiest way to deploy ofelia is using Docker. See examples above.
If don't want to run ofelia using our Docker image you can download a binary from releases page.
Why the project is named Ofelia? Ofelia is the name of the office assistant from the Spanish comic Mortadelo y Filemón