Table of Contents
You set up a cron job inside your Docker container. The logs show it firing. But nothing happens. No errors, no output, no evidence it actually ran. Welcome to the world of silent cron failures.
The Setup
You add a cron job to your container β maybe a periodic cleanup task, a file scan, or a scheduled PHP script:
*/15 * * * * php /var/www/html/artisan schedule:run >> /proc/1/fd/1 2>&1
Docker logs show the cron daemon triggering the job on schedule. You see lines like:
crond: USER www-data pid 7590 cmd php /var/www/html/artisan schedule:run >> /proc/1/fd/1 2>&1
But the actual command never executes. No output. No errors in your app logs. Nothing.
Two Silent Killers
1. The /proc/1/fd/1 Permission Trap
Redirecting output to /proc/1/fd/1 (PID 1’s stdout) is a common Docker pattern β it routes cron output to docker logs. But if your cron job runs as a non-root user (like www-data), that user can’t write to root’s file descriptors:
/bin/bash: line 1: /proc/1/fd/1: Permission denied
The cron daemon fires the job, the redirect fails, and the actual command never runs. The fix? Write to a file the user owns, or use /dev/stdout if your container setup allows it:
*/15 * * * * php /var/www/html/artisan schedule:run >> /tmp/cron.log 2>&1
2. Busybox crond and File Ownership
If you’re on Alpine Linux (common in Docker), you’re running busybox’s crond, not the full cron daemon. Busybox crond is extremely picky about crontab file ownership and permissions.
If you modify the crontab file directly (instead of using the crontab command), you can easily end up with wrong ownership:
$ ls -la /var/spool/cron/crontabs/www-data
-rw-r--r-- 1 root root 117 Jan 25 00:17 www-data
Busybox crond expects the crontab file to be owned by the user it belongs to. If www-data‘s crontab is owned by root, crond silently ignores it β no error, no warning, just… nothing.
The fix:
chown www-data:www-data /var/spool/cron/crontabs/www-data
chmod 600 /var/spool/cron/crontabs/www-data
The Debugging Checklist
Next time your Docker cron job “runs” but doesn’t actually do anything:
- Check output redirects β can the cron user actually write to the target?
- Check crontab ownership β does the file belong to the user, not root?
- Check permissions β crontab files should be 600
- Check which crond β
busybox crondvscrondhave different behaviors - Test the command manually as the cron user:
su -s /bin/sh www-data -c "your-command"
Silent failures are the worst kind of failures. At least now you know where to look.

Leave a Reply