Crontab in docker container

12,671

Few days ago i was struggling with similar problem and here are few notes based on what i have learnt first:

  • To be able to run a container like a service, somewhere (in cmd or entrypoint) must be a foreground program running. For your case it would be nginx -g daemon off; (from nginx image).

  • Also if there is an entrypoint and a cmd, they are launched in the way that the cmd is passed to the entrypoint as the argument (just like ./entrypoint.sh [cmd])

  • There is no point of having RUN /etc/init.d/cron start since after the image is built, it will be terminated anyway.

And to the solution: It was using entrypoint.sh similar to this one (in my case django/gunicorn/cron):

#!/bin/bash

set -e # exit on any error

if [ "$1" = './gunicorn.sh' ]; then  # './gunicorn.sh' is default command
  cron                               # this runs cron as daemon
  crontab -u django /app/crontab     # this applies a crontab from a file
  exec su django -c "$@"             # this actually runs the default command as different user (you can just use exec "$@" if you dont need to run it as different user)
fi

exec "$@" # this runs any other cmd without starting cron (e.g. docker run -ti myimage /bin/bash)
Share:
12,671

Related videos on Youtube

Kevin
Author by

Kevin

Updated on September 18, 2022

Comments

  • Kevin
    Kevin over 1 year

    Hi I'm trying to run a cron job in a docker container. So I have added that in my Dockerfile

    My Dockerfile

    FROM nginx:stable
    
    RUN apt-get update -y && apt-get upgrade -y && apt-get install -y \
        vim \
        git \
        curl \
        wget \
        certbot \
        cron
    
    COPY cron/crontab /etc/crontab
    RUN chmod 0644 /etc/cron.d/crontab
    RUN /etc/init.d/cron start 
    

    My crontab file

    # /etc/crontab: system-wide crontab
    # Unlike any other crontab you don't have to run the `crontab'
    # command to install the new version when you edit this file
    # and files in /etc/cron.d. These files also have username fields,
    # that none of the other crontabs do.
    
    SHELL=/bin/sh
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    
    # m h dom mon dow user command
    */1 *   *   *   * root echo "test" >>~/readme
    

    But it does not work.

    I have to run the command /etc/init.d/cron start manually in my nginx container if I want it to work.

    So I have added an entrypoint in my Dockerfile, so this command can be executed when the container start.

    # ENTRYPOINT
    ADD entrypoint.sh /entrypoint.sh
    RUN chmod 777 /entrypoint.sh
    

    My entrypoint.sh

    #!/usr/bin/env bash
    
    /etc/init.d/cron start
    

    My docker-compose

    entrypoint: /entrypoint.sh
    

    But I have this error:

    OCI runtime exec failed: exec failed: container_linux.go:296: starting container process caused "process_linux.go:86: executing setns process caused \"exit status 21\"": unknown

    Did I miss something?

    PS: I have followed this tutorial

    • jordanm
      jordanm about 6 years
      That guide is really wrong. Starting a service at build time makes no sense. Someone points that out in the article comments and the author just responds with "Did you read the start of the article?" which is a recommendation of not actually using the tutorial....
    • jordanm
      jordanm about 6 years
      Just use something like this image: hub.docker.com/r/hamiltont/docker-cron
  • Alessio
    Alessio about 6 years
    Note: it's a fairly common recommendation to run cron jobs on the docker host instead of inside each container. I prefer not to do that, I prefer containers to be entirely self-contained and not require any special configuration on the host. IMO requiring special per-container configuration defeats a large part of the automation and ephemeral re-usability benefits provided by containerising tasks.
  • Kevin
    Kevin about 6 years
    I have already done apt-get install cron. I'm using FROM nginx:stable... When I exec in my container and do service cron start it works perfectly. But I need the cron service to start automatically when the container is created. But it does not work
  • Alessio
    Alessio about 6 years
    what's nginx:stable based on? where did it come from? github.com/nginxinc/docker-nginx ? (there are alpine and debian stretch based versions there). somewhere else?
  • Kevin
    Kevin about 6 years
    It's the official stable version of nginx on docker hub, github.com/nginxinc/docker-nginx/blob/… .
  • Alessio
    Alessio about 6 years
    OK, according to the Dockerfile, that's based on Debian stretch. It already has CMD ["nginx", "-g", "daemon off;"] and I can't recall if you can run multiple commands with CMD or not. Maybe try something like CMD ["cron;", "nginx", "-g", "daemon off;"]. If that doesn't work, create a script that runs cron and then nginx -g daemon off, COPY it to your container, RUN chmod +x path/to/your/script, and add CMD /path/to/your/script.
  • Kevin
    Kevin about 6 years
    It does not work. My container does not strat. When I'm checking my nginx container logs, I have this message: Starting periodic command scheduler: cron. I have try your 2 solutions
  • Zach Smith
    Zach Smith about 5 years
    I have the case where a process creates a large number of temporary files. These files need to be kept for a week or so, so I would like a cronjob running inside the container to delete them these files if the container isn't recreated during that time. Is this a good use case for a cron job inside a docker container?