Containers
A Docker cron alternative that also monitors Kubernetes CronJobs
Stop running cron daemons inside containers. Trigger your jobs from outside with SteadyCron, or keep your existing Docker/K8s cron and just monitor it with a heartbeat.
The problem
Cron inside a container is a recurring source of pain: the daemon needs its own process babysitting in an otherwise single-process image, logs get trapped inside the container's stdout instead of your aggregator, and the container's timezone silently drifts from what you expect. Kubernetes CronJobs fix the daemon problem but not the visibility one — a CronJob that silently stops creating Pods (a paused schedule, a bad image, an exhausted backoff limit) fails completely silently. Nothing in kubectl tells you a job *should* have run an hour ago.
How SteadyCron solves it
- 1 Option A — move the trigger outside the container entirely: expose a simple HTTP endpoint in your app and let SteadyCron call it on schedule, with retries and a timeout. No cron daemon, no extra process, no timezone surprises inside the image.
- 2 Option B — keep your existing Docker cron or Kubernetes CronJob, and add a heartbeat: the job pings SteadyCron's ping URL on success (or /fail on error) as its last step.
- 3 Either way, SteadyCron tracks expected vs. actual: if the ping (or HTTP call) doesn't arrive within the grace period you set, the check goes from on-time to missed.
- 4 You get alerted the moment a CronJob stops firing — not when someone notices the nightly report didn't show up.
# Add to an existing Kubernetes CronJob: ping on success, alert on missed/failed
command: ["/bin/sh", "-c"]
args:
- >
./run-job.sh &&
curl -fsS https://ping.steadycron.com/$PING_TOKEN ||
curl -fsS https://ping.steadycron.com/$PING_TOKEN/fail
Jobs
| weekly-digest-email | HTTP | 0 9 * * 1 | in 2 days | 3 days ago | ||
| nightly-db-backup | Heartbeat | 0 2 * * * | in 19 h | 5 h ago | ||
| stripe-reconciliation | HTTP | 0 */4 * * * | in 38 min | 3 h ago | ||
| cache-warmup | HTTP | */15 * * * * | in 11 min | now | ||
| search-index-sync | Heartbeat | */30 * * * * | in 6 min | 24 min ago |
| seed-test-data | HTTP | 0 4 * * * | in 14 h | 10 h ago | ||
| preview-env-cleanup | Heartbeat | 0 */6 * * * | in 2 h | 4 h ago | ||
| trial-expiry-sweep | HTTP | 0 6 * * * | — | yesterday |
Every job's status, schedule, and last run — at a glance.
Two ways to fix container cron, depending on what you control
If you own the app code: drop the in-container cron entirely. Add an HTTP endpoint that runs the job’s logic, and let SteadyCron call it on a schedule from outside the container — with its own retry/backoff and a full request log. The container goes back to running one process, the way it’s supposed to, and the schedule lives in SteadyCron instead of in a crontab file that has to survive every image rebuild.
If you don’t want to touch the trigger (a Kubernetes CronJob someone else
owns, a Docker entrypoint you’d rather not refactor right now): leave it
running and add a heartbeat check. One curl at
the end of the script, and SteadyCron knows whether the job ran — and pages you
the moment it doesn’t, instead of you finding out from a downstream symptom.
Why container cron specifically breaks this way
- Docker: a cron daemon inside a container is a second long-running process
competing with the
PID 1your orchestrator actually supervises. If the daemon dies, the container looks healthy —docker psshows it running — while nothing inside it is actually firing. - Kubernetes CronJobs: the schedule itself is reliable (the controller is
part of the control plane), but failure is invisible by design. A CronJob
that hits its
backoffLimit, astartingDeadlineSecondsthat’s too tight for a busy cluster, or a bad image tag all fail the same way: no Pod, no error in your dashboards, just a job that quietly stopped happening.
See the platform-specific breakdowns if you’re debugging right now: Docker cron not running · Kubernetes CronJob not running.
A good fit for
- Nightly batch jobs, backups, and report generation currently triggered by a cron daemon baked into a Docker image.
- Kubernetes CronJobs for cleanup, sync, or maintenance tasks where a missed run is easy to overlook until it compounds.
- Teams moving toward a “schedule lives outside the container” model so scaling, redeploying, or migrating clusters doesn’t risk losing the schedule along with the Pod.
Related documentation
Stop finding out the hard way
Start on the free tier — no credit card required.
Start free