Yann Pellegrini

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?

Does the cron trigger?

⚠️
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