Situation
When creating a docker container (with docker run
oder docker compose up
) the USER
defined in the image (Dockerfile
) is used to create the hole filesystem inside the container.
Problem
When it is required to start the image (create the container) with root
to do some setup and dropping to a non-privileged user later to actually run the ‘final process’
then this non-privileged user cannot write to /dev/stdout
or /dev/stderr
which may be desired by the ‘final process’.
Example
See full setup at ‘docker-entrypoint-wrapper.sh’.
FROM nginxinc/nginx-unprivileged:1.27-alpine
USER root
## doing some extra setup work as root
#!/usr/bin/env sh
## doing some extra startup work as root, and then:
exec runuser -u nginx -- /docker-entrypoint-original.sh "${@}"
The image nginxinc/nginx-unprivileged
desires to write to /dev/stdout
and /dev/stderr
, as seen here near line 108:
# forward request and error logs to docker log collector
&& ln -sf /dev/stdout /var/log/nginx/access.log
&& ln -sf /dev/stderr /var/log/nginx/error.log
and docker run --rm -it nginxinc/nginx-unprivileged:1.27-alpine cat /etc/nginx/nginx.conf
:
[...]
error_log /var/log/nginx/error.log notice;
[...]
http {
[...]
access_log /var/log/nginx/access.log main;
[...]
What results in following error on startup of nginx using the non-privileged user
nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
Solution idea of ErikE or Anon (but this is ‘nginx’ specific)
The idea is to change the configuration (/etc/nginx/nginx.conf
) to not use the ‘file based logging’ in first place by doing following changes:
/var/log/nginx/error.log
withstderr
/var/log/nginx/access.log
withstdout
For exmaple with an ‘inplace replacement’ in the Dockerfile
RUN sed -i -e 's|/var/log/nginx/error.log|stderr|g' /etc/nginx/nginx.conf &&
sed -i -e 's|/var/log/nginx/access.log|stdout|g' /etc/nginx/nginx.conf
Solution idea of David Maze (does not work with docker compose
) (see comments on this post; added on 19.07.2024)
To change the ownership of /dev/stderr
and /dev/stdout
. Sidenote: these are actually ‘links’.
There are two different scenarios to have a look on:
- when starting the container with
docker compose
the link goes/dev/stderr -> /proc/self/fd/2 -> pipe:[1788860]
hence this no option because we cannot work withpipe:[1788860]
. (?) - when starting the container with
docker run
the link goes/dev/stderr -> /proc/self/fd/2 -> /dev/pts/0
hence this is an option because we canchown
on/dev/pts/0
. Sidenote: I only tested thechown
command not if the final process can make use of it (since my usecase is the ‘compose’ one)
Question
Is there a solution when using docker compose
that works for any ‘service’ (image)?
Since the “Solution idea of ErikE or Anon” is nginx specific.
bjoern-nowak is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
5