Docker: NGINX and PHP: Why change the default user/group?

523 Views Asked by At

I started learning about Docker and setting up NGINX and PHP. I looked at some examples and saw the following example: https://github.com/aschmelyun/lc-the-docker-tutorial/blob/main/nginx.dockerfile

There are two dockerfiles, one for NGINX (nginx.dockerfile):

FROM nginx:stable-alpine

ENV NGINXUSER=laravel
ENV NGINXGROUP=laravel

RUN mkdir -p /var/www/html/public

ADD nginx/default.conf /etc/nginx/conf.d/default.conf

RUN sed -i "s/user www-data/user ${NGINXUSER}/g" /etc/nginx/nginx.conf

RUN adduser -g ${NGINXGROUP} -s /bin/sh -D ${NGINXUSER}

and one for PHP (php.dockerfile):

FROM php:8-fpm-alpine

ENV PHPGROUP=laravel
ENV PHPUSER=laravel

RUN adduser -g ${PHPGROUP} -s /bin/sh -D ${PHPUSER}

RUN sed -i "s/user = www-data/user = ${PHPUSER}/g" /usr/local/etc/php-fpm.d/www.conf
RUN sed -i "s/group = www-data/group = ${PHPGROUP}/g" /usr/local/etc/php-fpm.d/www.conf

RUN mkdir -p /var/www/html/public

RUN docker-php-ext-install pdo pdo_mysql

CMD ["php-fpm", "-y", "/usr/local/etc/php-fpm.conf", "-R"]

In both cases new user & group are created (user laravel assigned to the group laravel), and then using sed command config files are modified:

  • For NGINX it replaces all occurrences of the user www-data with laravel in /etc/nginx/nginx.conf;
  • For PHP it does a similar thing: It replaces occurrences of user & group www-data with laravel.

3 interrelated questions:

Question 1: Does this mean that NGINX and PHP (I guess just FPM, and CLI will not be there because it pulls php:8-fpm-alpine base image from Docker Hub which doesn't include CLI, right?) will run as the laravel user inside containers? (If yes, please also look at Question 3).

Question 2: Is there any practical reason to change the default user for NGINX and PHP-FPM, as in the examples above?

Question 3: In php.dockerfile at the end there's this command:

CMD ["php-fpm", "-y", "/usr/local/etc/php-fpm.conf", "-R"]

I searched on Stackoverflow what this -R means, and I found the following answer: https://stackoverflow.com/a/49178410/4437206 If I understand correctly, this means that PHP-FPM will run as root? If so, then it will not run as the laravel user we added and therefore, what's the point of adding the laravel user?

3

There are 3 best solutions below

2
On BEST ANSWER

If you are going to run your images from an orchestrator (like kubernetes or openshift) running in unprivileged mode, you are not allowed to run processes as some user uids. The same applies for ports.

Nginx's root process always needs to starts as a root user, while it spawns child processes as the user you have provided. That's why there are unprivileged nginx images that fixes that. Php-fpm doesn't work like that, it just starts as the user stated in the Dockerfile or stated by the orchestrator.

And it's always a bad practice to run processes in your image as root, since the kernel of the host is available inside the container. If somebody get access to the shell of your running image, they will have access to the kernel and basically the entire host.

The same applies for ports, every listener on ports 1 to 1000 need to be bound by root. All the other ports from 1001 to 65535 don't. That's why you often see nginx port configuration on port 8080 and 8443.

To answer your last question, php-fpm -R is used to allow child processes to run as root, not to start as root.

1
On
  1. Yes.
  2. Running things as root inside of a container is still bad as root can and does have the ability to leverage exploits to escape the container. With non-root users this is much closer to impossible.
  3. -R just stops FPM from complaining about it, it does not actually change who is executing it.
1
On

But, by default, user that will be used by both NGINX and PHP-FPM is www-data, not root, so I guess in the examples above it was not really needed to change (replace) www-data with "laravel" user?

Let's assume you don't replace www-data with laravel.

In example you gave in link, docker volumes are used. That means, when "container up" process is finished (building and then applying volumes), container's files owner is root, but PHP user is www-data. You want be able to run such command like fopen() or mkdir() from your code, 'cause www-data doesn't have permissions to do something in root's filesystem with root's files.

Even if you create laravel user in Dockerfile (via USER instruction), problem will remain: laravel won't have appropriate permissions.

Those sed commands help with that: they replace www-data with some user, and not with random one, but with user, which id is the same as id of files owner in the host.

You can read more about it here. Please note that it was written by the same author whose code you provided a Github-link to.