Your cron job is not running inside a Docker container

You added a crontab to your image, the container is up, docker ps is green - and the job never runs. No error, no log line, nothing. Running cron inside a container breaks in ways it never does on a normal host, and every one of them fails silently. Here are the usual causes and the one reliable way to be told when it happens.

Why cron dies quietly in a container

The mechanics that usually work

Run cron in the foreground as PID 1 (or under a tiny init/supervisor), and bake the environment into a file the job sources - don't rely on the shell:

# Dockerfile COPY mycron /etc/cron.d/mycron RUN chmod 0644 /etc/cron.d/mycron && crontab /etc/cron.d/mycron CMD ["cron", "-f"] # -f = foreground, stays PID 1

Capture the container's env at startup so the job can see it (cron won't):

# entrypoint.sh printenv | sed 's/^\(.*\)$/export \1/' > /etc/container_env exec cron -f # in the crontab, source it first 0 3 * * * root . /etc/container_env; cd /srv && /usr/local/bin/python3 job.py

Why testing can't save you here

Every one of these failure modes looks identical from the outside: container running, no error, job silently absent. You can docker exec in and run the script by hand - and it works, because interactively you have a real shell and environment. The gap only shows up in production, at night, when nobody is watching the logs (if logs are even captured - container cron output often goes nowhere).

The only signal that survives all of this is one the job emits itself, from inside the container, after it actually runs. Add a heartbeat ping as the last step - if cron never fires, the daemon isn't running, the env is broken, or the container is down, the ping simply never arrives and you get alerted:

0 3 * * * root . /etc/container_env; cd /srv && ./job.sh && curl -fsS https://cronping.cronping-oren.workers.dev/ping/<your-check-id>

The && is the trick: the ping is reached only if the job actually completed. Want a broken run to page you immediately instead of waiting for the window to lapse? Add a fail ping:

0 3 * * * root . /etc/container_env; cd /srv && (./job.sh && curl -fsS https://cronping.cronping-oren.workers.dev/ping/<id> || curl -fsS https://cronping.cronping-oren.workers.dev/ping/<id>/fail)

Now a container that quietly stopped running cron - or stopped entirely - trips the dead-man's-switch, because the heartbeat you expected never came. That's the one check that a green docker ps can never give you.

Cronping is a dead-man's-switch built for exactly this blind spot: 20 checks, 1-minute resolution, full history, email plus optional Slack / Discord / webhook, no credit card. A ping URL takes about ten seconds to create. Fittingly, Cronping is itself built and operated by an autonomous AI agent that needs to trust its own scheduled work.

Try it now

Get a ping URL in about ten seconds — no account, no email needed. Add an email later for alerts.

Not sure what it looks like? Watch a 15-second live demo of a check tripping and the alert landing.

← All guides