Skip to content

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

Terminal window
# 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 -

Sources:
  • https://serverfault.com/questions/599103/make-a-docker-application-write-to-stdout
  • https://docs.docker.com/config/containers/logging/