Recipe: docker + crontab
Prerequisite: if you start from a base image, is it based on alpine or debian?
The syntax is not the same because debian uses cron 1 while alpine uses crond 2.
Check with:
$ docker run --rm ghcr.io/borgmatic-collective/borgmatic:latest cat /etc/os-release
Output:
NAME="Alpine Linux"
1. From a fresh Debian/Ubuntu base (crontab)
Dockerfile
1FROM debian:bookworm-slim
2
3RUN apt-get update && apt-get install -y cron && rm -rf /var/lib/apt/lists/*
4
5COPY entrypoint.sh /entrypoint.sh
6RUN chmod +x /entrypoint.sh
7ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh
1#!/bin/sh
2set -e
3
4(printenv | grep -v "^_="; echo "0 2 * * * /my/script.sh >> /var/log/cron.log 2>&1") | crontab -
5
6exec cron -f
Unlike with alpine, the environment variables are not available to the script if you miss the printenv part 3
2. From an existing image, based on Alpine: example of borgmatic (crond)
compose.yaml
1services:
2 borgmatic:
3 build: ./borgmatic
borgmatic/Dockerfile
1FROM ghcr.io/borgmatic-collective/borgmatic:latest
2
3COPY entrypoint.sh /entrypoint.sh
4RUN chmod +x /entrypoint.sh
5ENTRYPOINT ["/entrypoint.sh"]
6CMD []
borgmatic/entrypoint.sh
1#!/bin/sh
2set -e
3
4borgmatic init ... # Because we override the entrypoint, we need to insert the commands that it would have ran
5
6# 2 AM
7echo "0 2 * * * borgmatic 2>&1 | tee -a /var/log/cron.log" > /etc/crontabs/root
8
9exec crond -f
Unlike with Debian, environment variables are inherited. No tricks needed 4
Troubleshooting
Does the script work inside the container?
- Trigger the script manually:
docker exec <container> /my/script.sh
Does the cron trigger?
- Check if the cron is firing: run it every minute using
* * * * *and add a log:echo "$(date) cron fired" >> /var/log/cron.log; /my/script.sh
Note: output goes to /var/log/cron.log only, and will not show up in
docker logs <container>.
Instead use docker exec <container> tail -n 500 -f /var/log/cron.log