Skip to content

Instantly share code, notes, and snippets.

@mowings
Last active May 8, 2024 11:54
Show Gist options
  • Save mowings/59790ae930accef486bfb9a417e9d446 to your computer and use it in GitHub Desktop.
Save mowings/59790ae930accef486bfb9a417e9d446 to your computer and use it in GitHub Desktop.
Run cron on docker with job output directed to stdout

You'd like a docker container that runs cron jobs, with the output of those cron jobs going to stdout so they are accessible as docker logs. How do you do that?

Install cron, and set it up to run in the foreground

In your Dockerfile, apt-get -y install cron Use apk or whatever if you are running on alpine or another distribution Set the command or entrypoint in your Dockerfile to run cron 9n the foreground

ENTRYPOINT ["/usr/sbin/cron", "-f"]

Create the crontab with redirection

Copy the crontab with your jobs in it into /etc/crontab. Each job should redirect it's stdout and stderr to fh 1 of PID 1 (the crontab process). Here's a simple example crontab:

SHELL=/bin/sh 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

* * * * * root echo "HELLO!" > /proc/1/fd/1 2>&1

This just prints "HELLO" every minute, redirecting the echo output to process 1's stdout (file handle 1). This line also redirects stderr, although that is not really necessary in the case of a simple echo.

This works because docker always treats the stdout from process 1 as the docker log stream.

An even simpler way

... to run a single job on a regular basis is to use date and sleep. This makes for a simpler container (no need for cron) if you only need a command or commands to run at a single interval (say, every morning at 3:00AM). Details in this gist

@x-yuri
Copy link

x-yuri commented Jun 28, 2022

I probably made an example with rsyslog because in some cases crontab can be generated (e.g. ruby's whenever), I'm not sure. The suggested solution works:

docker-compose.yml:

services:
  d:
    build: .
    init: yes

Dockerfile:

FROM debian:bullseye-slim
RUN set -x && apt update && apt install -y cron \
    && echo '* * * * * root echo "HELLO!" > /proc/1/fd/1 2>&1' > /etc/cron.d/myjob
CMD ["/usr/sbin/cron", "-f"]

Under Alpine Linux:

docker-compose.yml:

services:
  d:
    build: .

Dockerfile:

FROM alpine
RUN set -x && apk add --no-cache dcron \
    && echo '* * * * * echo "HELLO!" > /proc/1/fd/1 2>&1' > /etc/cron.d/myjob
CMD ["/usr/sbin/crond", "-f"]

Which exits with:

setpgid: Operation not permitted

But it can be worked around like so:

docker-compose.yml:

services:
  d:
    build: .
    init: yes

Dockerfile:

FROM alpine
RUN set -x && apk add --no-cache dcron \
    && echo '* * * * * echo "HELLO!" > /proc/1/fd/1 2>&1' > /etc/cron.d/myjob
COPY dcron.sh .
CMD ["/dcron.sh"]

dcron.sh:

#!/bin/sh -e
# https://github.com/dubiousjim/dcron/issues/13#issuecomment-340382335
crond -f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment