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