nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.39k stars 327 forks source link

containerized Django logging best practices #692

Open sebastian-philipp opened 2 years ago

sebastian-philipp commented 2 years ago

Hi folks,

I was looking into getting logging of my Django app to work in a containerized unit, but not sure how to get it right.

General best practice for containers is to log to stdout and that's what I tried to do like so:

# settings.py
LOGGING = {
    ...,
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'stream': sys.stdout,
            'formatter': 'verbose',
        },
    },
    ...,
}

But this doesn't work, as AFAICS nginx-unit is spawning a new process for the app. An alternative would be to write the log to the main process as in 'stream': open('/proc/1/fd/1', 'a') but that fails with a permission denied error.

My main idea was to avoid deploying an extra sidecar container just for printing the Django log to stdout.

What is the best practice for setting up Django logging in a container?

Thank you!

sebastian-philipp commented 2 years ago

fyi, I ended up with creating an intermediate ENTRYPOINT like so:

$ cat my-entrypoint.sh
#/bin/bash

set -e

touch /tmp/django.log
chmod a+w /tmp/django.log
nohup tail -f /tmp/django.log &

exec /usr/local/bin/docker-entrypoint.sh "unitd" "--no-daemon" "--control" "unix:/var/run/control.unit.sock"
tippexs commented 2 years ago

Hi @sebastian-philipp . I was literally working on the same approach but was looking for something more elegant but couldn't find anything, yet.

So for now I believe this is the best way doing it. Maybe you can keep the default docker-entrypoint.sh script and use a shell script in the docker-entrypoint.d directory. More information here: https://unit.nginx.org/installation/#docker-images

Given the Unit state directory is empty, Unit would execute the script. We could try using this script so you could use the default Docker Image without overwriting the entrypoint.

sebastian-philipp commented 2 years ago

Hi @sebastian-philipp . I was literally working on the same approach but was looking for something more elegant but couldn't find anything, yet.

So for now I believe this is the best way doing it. Maybe you can keep the default docker-entrypoint.sh script and use a shell script in the docker-entrypoint.d directory. More information here: https://unit.nginx.org/installation/#docker-images

Given the Unit state directory is empty, Unit would execute the script. We could try using this script so you could use the default Docker Image without overwriting the entrypoint.

Would that also work for container restarts?

jalaziz commented 2 years ago

Other app servers tend to have an option to forward stdout/stderr from child processes to the parent process. Would be nice if Unit could handle this automatically.

tippexs commented 2 years ago

Hi @sebastian-philipp . I was literally working on the same approach but was looking for something more elegant but couldn't find anything, yet. So for now I believe this is the best way doing it. Maybe you can keep the default docker-entrypoint.sh script and use a shell script in the docker-entrypoint.d directory. More information here: https://unit.nginx.org/installation/#docker-images Given the Unit state directory is empty, Unit would execute the script. We could try using this script so you could use the default Docker Image without overwriting the entrypoint.

Would that also work for container restarts?

No - That is the issue in this case. The script will be executed if and only the NGINX Unit state dir is empty. In this case using our pre-build Image as a base image and override the entrypoint would be the best option.