Fehlerbehebung · Docker
Cron im Docker-Container läuft nicht? Lösungen, die wirklich funktionieren
Warum Cron in einem Docker-Container still ausfällt — PID 1, fehlende Env-Variablen, kein Mailserver — und wie Sie jedes Problem beheben.
Cron in einem Container laufen zu lassen, bringt Leute aus dem Tritt, weil ein Container keine normale VM ist. Hier die üblichen Ursachen, lösungsorientiert.
1. Cron läuft nicht als PID 1
Ein Container führt einen Vordergrundprozess aus. Startet Ihr CMD Ihre App, wird
cron nie gestartet — und ist Ihr CMD cron, beendet es sich womöglich sofort,
weil es sich daemonisiert. Führen Sie es im Vordergrund aus:
# Debian/Ubuntu-Basis
CMD ["cron", "-f"]
Um Cron und Ihre App auszuführen, nutzen Sie einen kleinen Supervisor
(supervisord, s6) oder einen Prozessmanager — verlassen Sie sich nicht auf
Backgrounding in einem Shell-CMD.
2. Umgebungsvariablen verschwinden unter Cron
Das ist das große Problem. Docker injiziert Env-Variablen in PID 1, aber Cron
startet Jobs mit einer sauberen Umgebung, sodass Ihre DATABASE_URL und
API-Schlüssel weg sind. Schreiben Sie die Container-Umgebung beim Start in eine
Datei und laden Sie sie im Job:
CMD printenv | sed 's/^\(.*\)$/export \1/' > /etc/container.env && cron -f
# in der Crontab
0 * * * * . /etc/container.env && /app/run.sh
3. Die Crontab braucht das richtige Format und eine Leerzeile am Ende
Eine System-Crontab-Zeile braucht eine Benutzer-Spalte, und die Datei muss mit einer Newline enden, sonst wird der letzte Job ignoriert:
# /etc/cron.d/app — beachten Sie das Benutzerfeld "root"
0 2 * * * root /app/run.sh >> /var/log/cron.log 2>&1
COPY app-cron /etc/cron.d/app
RUN chmod 0644 /etc/cron.d/app && crontab /etc/cron.d/app
4. „Cron kann keine E-Mail senden“ — es gibt keinen Mailserver
Ein Klassiker: Eine Container-Crontab versucht, die Ausgabe zu mailen, aber es gibt
keinen MTA, sodass Jobs scheinbar „fehlschlagen“. Verlassen Sie sich nicht auf
lokale Mail. Leiten Sie die Ausgabe nach stdout, damit sie in docker logs landet:
0 2 * * * root /app/run.sh > /proc/1/fd/1 2>/proc/1/fd/2
5. Sehen Sie sich die Ausgabe an
docker logs -f <container>
docker exec -it <container> sh -c "crontab -l"
Das tiefere Problem: Container starten neu, und Cron vergisst
Ein Redeploy, ein OOM-Kill, eine Crash-Loop — jedes davon kann Ihren Container-Cron stoppen, und nichts sagt es Ihnen. Monitoring von außerhalb des Containers ist das einzig zuverlässige Signal.
Lassen Sie den Job bei Erfolg eine Heartbeat-URL anpingen. Ist der Container down oder der Job gestoppt, bleibt der Ping aus und Sie werden alarmiert:
HEALTHCHECK --interval=5m --timeout=10s \
CMD curl -fsS https://ping.steadycron.com/<ihr-ping-token> || exit 1