1

I build a Docker image to run a crontab file:

RUN apt-get install -y cron
RUN touch /usr/local/learnintouch/cron.log
COPY learnintouch.cron /usr/local/learnintouch/
RUN chmod 0644 /usr/local/learnintouch/learnintouch.cron \
  && sudo crontab /usr/local/learnintouch/learnintouch.cron

It has an ENTRYPOINT to run a start.sh file which contains:

# Run the crontab
sudo service cron start

The learnintouch.cron file contains:

* * * * * echo "Hello cron" >> /usr/local/learnintouch/logs/cron.log 2>&1

But the log shows nothing.

Only if I connect in the container and run the start.sh file manually, that is, as the root user, does the log show the Hello cron message.

When logged in the container, the files have the apache user:

root@72f59adb5324:/usr/local/learnintouch# ll
total 2852
drwxr-xr-x  1 apache apache    4096 May 11 19:42 ./
drwxr-xr-x  1 root   root      4096 May  3 20:10 ../
-rwxr-xr-x  1 apache apache       0 May 11 18:56 cron.log*
-rwxr-xr-x  1 apache apache    1057 May 11 19:34 start.sh*
root@72f59adb5324:/usr/local/learnintouch# whoami
root

I reckon it's a user permissions issue.

UPDATE: I tried replicating the issue with a Dockerfile as in:

FROM ubuntu:20.10

RUN apt-get update \
  && apt-get install -y sudo \
  && apt-get autoremove -y && apt-get clean

RUN mkdir -p /usr/local/learnintouch/
RUN apt-get install -y cron
COPY learnintouch.cron /usr/local/learnintouch/
RUN chmod 0644 /usr/local/learnintouch/learnintouch.cron \
  && crontab /usr/local/learnintouch/learnintouch.cron

ENTRYPOINT ["/usr/sbin/cron", "tail", "-f", "/dev/null"]

After building the image:

docker build -t stephaneeybert/cronissue .

and running the container:

docker run --name cronissue -v ~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs stephaneeybert/cronissue 

the cron started working fine and the issue would NOT show up.

So I reckoned the issue could lie within the docker-compose.yml file I use.

I thus tried running with the docker-compose.yml file:

version: "3.7"
services:
  cronissue:
    image: stephaneeybert/cronissue
    volumes:
      - "~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs"

with the Docker Swarm command:

docker stack deploy --compose-file docker-compose.yml cronissue

And again the cron started working fine and the issue would NOT show up.

So I finally added the user: "${CURRENT_UID}:${CURRENT_GID}" property that I also have in my project as in:

version: "3.7"
services:
  cronissue:
    image: stephaneeybert/cronissue
    volumes:
      - "~/dev/docker/projects/common/volumes/logs:/usr/local/learnintouch/logs"
    user: "${CURRENT_UID}:${CURRENT_GID}"

And this time, the cron did NOT work and the issue showed up.

The issue shows up ONLY when I run the container with the host user.

As a side note, I also tried opening the file permissions but it did not change anything:

  && chmod a+x /usr/bin/crontab \
  && chmod a+x /usr/sbin/cron \

UPDATE: I ended up using supercronic instead of cron as it works fine in containers.

# Using supercronic as a cron scheduler
# See https://github.com/aptible/supercronic/
COPY supercronic-linux-amd64 /usr/local/learnintouch
COPY learnintouch.cron /usr/local/learnintouch/
RUN chmod 0644 /usr/local/learnintouch/learnintouch.cron
Stephane
  • 11,836
  • 25
  • 112
  • 175
  • Does this answer your question? [How to run a cron job inside a docker container?](https://stackoverflow.com/questions/37458287/how-to-run-a-cron-job-inside-a-docker-container) – Antwane May 11 '21 at 20:22
  • No, in fact, that's where I went to first and from what I created my own attempt :-) – Stephane May 11 '21 at 20:26
  • 3
    In general, running `service` in a container won't do anything (because there is no service manager running). If you want to start something like the cron daemon, start it yourself (e.g., `ENTRYPOINT ["crond", "-n"]` (noting, of course, that the name of your cron daemon and the arguments it expects to run in the foreground will vary depending on your distribution). – larsks May 11 '21 at 20:42
  • @larsks Enlightening. But in fact, I had started with the simple `cron` command before switching to a `service cron start` command. It also didn't run the `cron`. Now I tried a `sudo cron` command but it didn't run it either. – Stephane May 12 '21 at 19:46
  • 1
    Running `cron` via `ENTRYPOINT` or `CMD` -- with the proper flags such that it runs in the foreground -- works just fine. If you've tried that and it didn't work, please update your question to show a `Dockerfile` that reproduces the problem and we can probably help figure things out. – larsks May 12 '21 at 19:50
  • @larsks I added a `Dockerfile` and a `docker-compose.yml` illustrating the issue. – Stephane May 13 '21 at 09:24

1 Answers1

1

First, the command in ENTRYPOINT doesn't make sense. You've got:

ENTRYPOINT ["/usr/sbin/cron", "tail", "-f", "/dev/null"]

It looks like you're trying to combine two commands here (cron and tail -f /dev/null), but you can't just mash together commands like that. It looks like you're using the tail -f /dev/null to try to keep the container running after cron background itself, but that's unnecessary -- looking at the man page, we can use the -f flag to cron to keep it in the foreground, so that becomes:

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

Fortunately, the way you've got things configured, cron is just ignoring the unknown arguments (you can run cron this is a test -f and it works) so you're accidentally doing the right thing.

The issue shows up ONLY when I run the container with the host user.

The cron daemon is designed to run as root. If I try starting your image as a non-root user, for example using your docker-compose.yml that sets the user, I get:

cronissue_1  | cron: can't open or create /var/run/crond.pid: Permission denied

And even if you fix that problem by changing the directory ownership, cron will still fail:

$ cron -f
seteuid: Operation not permitted

You'll need to run cron as root, or you'll need to find some other tooling if you really want to run a scheduler as a non-root user.


As a side note, I also tried opening the file permissions but it did not change anything:

&& chmod a+x /usr/bin/crontab \
&& chmod a+x /usr/sbin/cron \

Note that the above commands are no-ops; both commands are already executable by everyone so you haven't changed anything.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • I run the container as the host user so as to write in the log mapped host volume. I guess I could ditch the volume mapping and run it as root then. – Stephane May 13 '21 at 12:57