1

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

3
  • 1
    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
    Mar 8, 2018 at 17:26
  • Just use something like this image: hub.docker.com/r/hamiltont/docker-cron
    – jordanm
    Mar 8, 2018 at 17:27
  • */1 looks ugly and it is a waste of 2 keystrokes
    – Bruno9779
    Mar 8, 2018 at 18:22

2 Answers 2

1

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)
0

What are you using as the base for your Docker image (i.e. what's in the FROM line)?

Many docker base images start with a minimal install of an existing distribution (e.g. alpine, debian, ubuntu, centos, etc) and then you add whatever packages you need to it.

If your base image doesn't include cron by default, install it in your Dockerfile using the distribution's appropriate package tool (e.g. apt-get install cron), and then configure it as you would on any other system - e.g. by adding an entry to a system crontab file like /etc/crontab, or by dropping an executable script in /etc/cron.d.

In some cases, cron may be installed but disabled. You need to modify your container's startup script so that it starts crond. This is not the same as using the RUN command in the Dockerfile (that's for running commands during the container build process, not on startup of each container). The details of how to do that vary according to the base image you used.

7
  • 1
    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.
    – cas
    Mar 9, 2018 at 2:49
  • 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
    – Kevin
    Mar 9, 2018 at 10:02
  • 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?
    – cas
    Mar 9, 2018 at 15:21
  • It's the official stable version of nginx on docker hub, github.com/nginxinc/docker-nginx/blob/… .
    – Kevin
    Mar 9, 2018 at 19:19
  • 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.
    – cas
    Mar 10, 2018 at 1:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .