7

Trying to run a docker container that has a cron scheduling. However I cannot make it output logs.

Im using docker-compose.

docker-compose.yml

---
version: '3'
services:
  cron:
    build:
      context: cron/
    container_name: ubuntu-cron

cron/Dockerfile

FROM ubuntu:18.10

RUN apt-get update
RUN apt-get update && apt-get install -y cron 

ADD hello-cron /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Run the command on container startup
CMD cron && tail -F /var/log/cron.log

cron/hello-cron

* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1

The above runs fine its outputting logs inside the container however they are not streamed to the docker.

e.g. docker logs -f ubuntu-cron returns empty results

but

if you login to the container docker exec -it -i ubuntu-cron /bin/bash you have logs.

cat /var/log/cron.log 
Hello world
Hello world
Hello world

Now Im thinking that maybe I dont need to log to a file? could attach this to sttoud but not sure how to do this.

This looks similar... How to redirect cron job output to stdout

Robbo_UK
  • 11,351
  • 25
  • 81
  • 117

3 Answers3

7

I tried your setup and the following Dockerfile works:

FROM ubuntu:18.10

RUN apt-get update
RUN apt-get update && apt-get install -y cron

ADD hello-cron /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0755 /etc/cron.d/hello-cron

# Create the log file to be able to run tail
RUN touch /var/log/cron.log

# Symlink the cron to stdout
RUN ln -sf /dev/stdout /var/log/cron.log

# Run the command on container startup
CMD cron && tail -F /var/log/cron.log 2>&1

Also note that I'm bringing the container up with "docker-compose up" rather than docker. It wouldn't matter in this particular example, but if your actual solution is bigger it might matter.

EDIT: Here's the output when I run docker-compose up:

neekoy@synchronoss:~$ sudo docker-compose up
Starting ubuntu-cron ... done
Attaching to ubuntu-cron
ubuntu-cron | Hello world
ubuntu-cron | Hello world
ubuntu-cron | Hello world

Same in the logs obviously:

neekoy@synchronoss:~$ sudo docker logs daf0ff73a640
Hello world
Hello world
Hello world
Hello world
Hello world

My understanding is that the above is the goal.

alexkb
  • 3,216
  • 2
  • 30
  • 30
Neekoy
  • 2,325
  • 5
  • 29
  • 48
  • Doesnt work for me. "RUN ln -sf" resutls in the file always being empty. take that out and the logs are populated but they are not streamed to the docker compose output – Robbo_UK Jul 20 '18 at 10:58
  • @Robbo_UK In the OP it was mentioned that we don't need the output in a file. Let me know if you want it both in a file and in stdout. Also, I made an edit to my post with output of stdout when I run the container. – Neekoy Jul 20 '18 at 11:30
  • output to sttdout is fine. what does your hello-cron look like. – Robbo_UK Jul 20 '18 at 12:14
  • The same as yours. Basically just add that row I referenced and run "docker-compose up". – Neekoy Jul 20 '18 at 12:39
  • hmm its not working for me... I do think that this is the correct answer. Ive put it on github. Must be something different that is missed? https://github.com/davidsonr/docker-ubuntu-cron – Robbo_UK Jul 20 '18 at 13:22
  • For anyone using a debian derived docker image, you also need to make sure rsyslog is installed for the above answer to log things to /dev/stdout properly. So just append it to the install cron command like so `RUN apt-get update && apt-get install -y cron rsyslog`. – alexkb Sep 13 '18 at 06:37
6

Due to some weirdness in the docker layers and inodes, you have to create the file during the CMD:

CMD cron && touch /var/log/cron.log && tail -F /var/log/cron.log

This works both for file and stdout:

FROM ubuntu:18.10

RUN apt-get update
RUN apt-get update && apt-get install -y cron

ADD hello-cron /etc/cron.d/hello-cron

# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron

# Create the log file to be able to run tail
# Run the command on container startup
CMD cron && touch /var/log/cron.log && tail -F /var/log/cron.log

The explanation seems to be this one:

In the original post tail command starts "listening" to a file which is in a layer of the image, then when cron writes the first line to that file, docker copies the file to a new layer, the container layer (because of the nature of copy-and-write filesystem, the way that docker works). So when the file gets created in a new layer it gets a different inode and tail keeps listening in the previous state, so looses every update to the "new file". Credits BMitch

Robert
  • 33,429
  • 8
  • 90
  • 94
  • As this will not logrotate the cron.log file it may grow very large depending on your cron output.. – Micronax Dec 11 '18 at 21:28
0

Try to redirect on this > /dev/stdout, after this you should see your logs with a docker logs.

Kilian
  • 1,753
  • 13
  • 21
  • think this is on the right path.. However the ubuntu container exits. May need something from here to keep it running https://stackoverflow.com/questions/25775266/how-to-keep-docker-container-running-after-starting-services – Robbo_UK Jul 18 '18 at 10:36