Dépannage · Docker

Cron dans un conteneur Docker qui ne tourne pas ? Des correctifs qui marchent

Pourquoi cron échoue en silence dans un conteneur Docker — PID 1, variables d’env manquantes, pas de serveur mail — et comment corriger chaque cas.

Faire tourner cron dans un conteneur déroute, car un conteneur n’est pas une VM normale. Voici les coupables habituels, orientés solution.

1. Cron ne tourne pas en tant que PID 1

Un conteneur exécute un processus au premier plan. Si votre CMD lance votre app, cron ne démarre jamais — et si votre CMD est cron, il peut se terminer immédiatement car il se daemonise. Exécutez-le au premier plan :

# base Debian/Ubuntu
CMD ["cron", "-f"]

Pour exécuter cron et votre app, utilisez un petit superviseur (supervisord, s6) ou un gestionnaire de processus — ne comptez pas sur le backgrounding dans un CMD shell.

2. Les variables d’environnement disparaissent sous cron

C’est le gros point. Docker injecte les variables d’env dans le PID 1, mais cron démarre les tâches avec un environnement vierge : votre DATABASE_URL et vos clés d’API ont disparu. Exportez l’environnement du conteneur dans un fichier au démarrage et chargez-le dans la tâche :

CMD printenv | sed 's/^\(.*\)$/export \1/' > /etc/container.env && cron -f
# dans la crontab
0 * * * * . /etc/container.env && /app/run.sh

3. La crontab a besoin du bon format et d’une nouvelle ligne

Une ligne de crontab système a besoin d’une colonne utilisateur, et le fichier doit se terminer par une nouvelle ligne, sinon la dernière tâche est ignorée :

# /etc/cron.d/app  — notez le champ utilisateur "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 ne peut pas envoyer d’e-mail » — il n’y a pas de serveur mail

Un classique : une crontab de conteneur tente d’envoyer la sortie par e-mail, mais il n’y a pas de MTA, donc les tâches semblent « échouer ». Ne dépendez pas du mail local. Redirigez la sortie vers stdout pour qu’elle apparaisse dans docker logs :

0 2 * * * root /app/run.sh > /proc/1/fd/1 2>/proc/1/fd/2

5. Consultez la sortie

docker logs -f <container>
docker exec -it <container> sh -c "crontab -l"

Le problème de fond : les conteneurs redémarrent, et cron oublie

Un redéploiement, un OOM kill, une boucle de crash — chacun peut arrêter votre cron intra-conteneur, et rien ne vous le dit. La surveillance depuis l’extérieur du conteneur est le seul signal fiable.

Faites pinguer une URL heartbeat par la tâche en cas de succès. Si le conteneur est arrêté ou la tâche stoppée, le ping manque et vous êtes alerté :

HEALTHCHECK --interval=5m --timeout=10s \
  CMD curl -fsS https://ping.steadycron.com/<votre-jeton-ping> || exit 1