'See cron output via docker logs, without using an extra file
I am running "cron" in a docker container.
Every day a script is executed.
The output of this script I would like to see via "docker logs "
The process with PID 0 is the cron daemon in my container. Entrypoint starts cron in foreground:
/usr/sbin/crond -f
I understand, that I could redirect the script output to a file "path/to/logs"
07 2 * * * /data/docker/backup_webserver/backupscript.sh >> path/to/logs
and start the container as following to see the logs
"tail -f path/to/logs"
But then the file "path/to/logs" would grow during the runtime of the container.
Is there a possibility to log from crontab, directly to "docker logs" ?
Solution 1:[1]
Change your cron file to below
07 2 * * * /data/docker/backup_webserver/backupscript.sh > /dev/stdout
This will make sure the logs go to the container output
Solution 2:[2]
Alpine: No need for redirection
using the default cron utility (busybox)
Dockerfile
FROM alpine:3.7
# Setting up crontab
COPY crontab /tmp/crontab
RUN cat /tmp/crontab > /etc/crontabs/root
CMD ["crond", "-f", "-l", "2"]
crontab
* * * * * echo "Crontab is working - watchdog 1"
Centos:
Redirection to /proc/1/fd/1
inside the crontab declaration line
Dockerfile
FROM centos:7
RUN yum -y install crontabs
ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN crontab /etc/cron.d/crontab
CMD ["crond", "-n"]
crontab
* * * * * echo "Crontab is working - watchdog 1" > /proc/1/fd/1
Solution 3:[3]
@mcfedr is correct, but it took me a while to understand it with it being a one-liner with variables and some extra code related to setting up cron.
This may be a little bit easier to read. It helped me to write it out explicitly.
# Create custom stdout and stderr named pipes
mkfifo /tmp/stdout /tmp/stderr
chmod 0666 /tmp/stdout /tmp/stderr
# Have the main Docker process tail the files to produce stdout and stderr
# for the main process that Docker will actually show in docker logs.
tail -f /tmp/stdout &
tail -f /tmp/stderr >&2 &
# Run cron
cron -f
Then, write to those pipes in your cron:
* * * * * /run.sh > /tmp/stdout 2> /tmp/stderr
Solution 4:[4]
fifo is the way to go, it also useful because it allows cron tasks that are not running as root to write to the output.
I am using a CMD along these lines
ENV LOG_STREAM="/tmp/stdout"
CMD ["bash", "-o", "pipefail", "-c", "mkfifo $$LOG_STREAM && chmod 777 $$LOG_STREAM && echo -e \"$$(env | sed 's/=\\(.*\\)/=\"\\1\"/')\n$$(cat /etc/cron.d/tasks)\" > /etc/cron.d/tasks && cron -f | tail -f $$LOG_STREAM"]
With the tasks in /etc/cron.d/tasks
* * * * */10 www-data echo hello >$LOG_STREAM 2>$LOG_STREAM
I also prepend the env at launch to tasks
so it's visible to the tasks, as cron doesnt pass it though by itself. The sed
is needed because crontab format requires env vars to be quoted - at least it requires empty vars to be quoted and fails to run tasks if you have an empty var without quotes.
Solution 5:[5]
You could just use a FIFO.
mkfifo path/to/logs
When processes exchanging data via the FIFO, the kernel passes all data without writing it to the filesystem. Thus, the FIFO special has no contents on the filesystem; the filesystem entry merely serves a reference point so that processes can access the pipe using a in the filesystem.
Solution 6:[6]
For Debian-based images, following Dockerfile
works for me (note that /etc/crontab
has a slightly different format, compared to user crontab files):
FROM debian:buster-slim
RUN apt-get update \
&& apt-get install -y cron
RUN echo "* * * * * root echo 'Crontab is working - watchdog 1' > /proc/1/fd/1 2>/proc/1/fd/2" > /etc/crontab
CMD ["cron", "-f"]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tarun Lalwani |
Solution 2 | MaxBlax360 |
Solution 3 | kirkmadera |
Solution 4 | |
Solution 5 | Matthias Simonis |
Solution 6 | mstrap |