Writing logs in a container
Notes
- In a container it is said that /dev/stdout and /dev/stderr are written to the logging driver.
- Actually, In a container the /dev/'s are system linked to other locations.
lrwxrwxrwx. 1 root root 15 May 16 12:07 stderr -> /proc/self/fd/2 lrwxrwxrwx. 1 root root 15 May 16 12:07 stdin -> /proc/self/fd/0 lrwxrwxrwx. 1 root root 15 May 16 12:07 stdout -> /proc/self/fd/1
- In a container only PID1 and processes forked by it are captured by the above. Any other process that is running will not be visible in the
docker|podman logs
output. - In your Containerfile whatever you
CMD
orENTRYPOINT
is PID1.
Logging PID1
The official nginx
image creates a symbolic link from /var/log/nginx/access.log to /dev/stdout, and creates another symbolic link from /var/log/nginx/error.log to /dev/stderr, overwriting the log files and causing logs to be sent to the relevant special device instead. See the Dockerfile.
Example
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
Logging processes other than PID1
To log processes other than PID1 you need to send data to /proc/1/fd/1 for stdout and /proc/1/fd/2 for stderr.
Example
# set a crontab renewal of certs
SLEEPTIME=$(awk 'BEGIN{srand(); print int(rand()*(3600+1))}'); \
echo "0 0,12 * * * root sleep $SLEEPTIME && certbot renew -q && echo 'cerbot renewed' >> /proc/1/fd/1" | crontab -