Home > Blockchain >  How to run httpd:2.4-alpine docker image not as root user
How to run httpd:2.4-alpine docker image not as root user

Time:08-31

I try to run httpd:2.4-alpine docker image not as a root user.

Default behavior :

> docker run -p 80:80 -d --rm --name httpd httpd:2.4-alpine
3c271ae8abfc3f54c0e63d62a2ce26fcbeeef29064da66f4b3f6bd00480ad4fb
> docker exec httpd --name httpd whoami
root

After looking inside the Dockerfile definition of this image, one can see a www-data is created with an id 82 :

...
RUN set -x \
    && adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
...

Let's try to run this image using this user then :

> docker stop httpd # cleaning previous instance
> docker run -p 80:80 --rm --name httpd -u www-data httpd:2.4-alpine

This failed with this error :

AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message [Tue Aug 30 15:57:25.958695 2022] [core:error] [pid 1:tid 140459379268424] (13)Permission denied: AH00099: could not create /usr/local/apache2/logs/httpd.pid.XXXXXX [Tue Aug 30 15:57:25.959029 2022] [core:error] [pid 1:tid 140459379268424] AH00100: httpd: could not log pid to file /usr/local/apache2/logs/httpd.pid

I've found this answer that seems to fix the problem, but because I'm in a docker context I don't know how/if I can apply this solution.

Does someone out there know how I could run this image NOT as a root ?

CodePudding user response:

While @javierlga's answer is correct, you don't need to build a new image to remediate this issue. There are three things we need to do:

  1. Run Apache as the www-data user
  2. Grant the www-data user the ability to bind to privileged ports, and
  3. Deal with the need to write a pid file into /usr/local/apache2/logs.

We can accomplish (1) using the -u argument to docker run:

docker run -u www-data ...

We can solve (2) using with the --cap-add argument to docker run:

docker run -u www-data --cap-add net_bind_service ...

That leaves us with (3). We can see the problem in the logs you posted in your question:

Permission denied: AH00099: could not create /usr/local/apache2/logs/httpd.pid.XXXXXX

Apache is trying to write a file into /usr/local/apache2/logs, but the www-data user does not have permission to create files in this directory.

There are a number of ways of solving this problem. The simplest is probably moving the pidfile to /tmp, which we can do by passing the necessary configuration directive to httpd using the -C command line option:

docker run ... docker.io/httpd:2.4.54-alpine \
  httpd-foreground -C 'PidFile /tmp/httpd.pid'

Putting it all together, we get:

docker run -u www-data \
  --cap-add net_bind_service -p 8080:80 \
  docker.io/httpd:2.4.54-alpine \
  httpd-foreground -C 'PidFile /tmp/httpd.pid'

Or in a docker-compose.yaml file:

version: "3"

services:
  httpd:
    image: docker.io/httpd:2.4.54-alpine
    command: [httpd-foreground, -C, "PidFile /tmp/httpd.pid"]
    user: www-data
    ports:
      - "8080:80"
    cap_add:
      - net_bind_service

That runs without errors and does not require maintaining our own image.

CodePudding user response:

The reason for this is that by default the user www-data lacks the capability to bind a privileged port, in fact, any other regular will have the same issue.

As you can see, only the parent process runs as the root user, and child processes run as the www-data user.

/usr/local/apache2 # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 httpd -DFOREGROUND
    8 www-data  0:00 httpd -DFOREGROUND
    9 www-data  0:00 httpd -DFOREGROUND
   10 www-data  0:00 httpd -DFOREGROUND
   92 root      0:00 sh
   98 root      0:00 ps aux

By setting setcap 'cap_net_bind_service= ep' to the httpd binary, you'll be able to run it as the www-data user.

In order to fix this, you need to create a new image, this is a Dockerfile example:

FROM httpd:2.4-alpine

RUN apk add libcap && chown -hR www-data:www-data /usr/local/apache2/ && \
  setcap 'cap_net_bind_service= ep' /usr/local/apache2/bin/httpd

USER www-data

Once you have created the new image, you'll be able to run the image as non-root.

Logs:

AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Tue Aug 30 16:51:43.660323 2022] [mpm_event:notice] [pid 1:tid 281473523657800] AH00489: Apache/2.4.54 (Unix) configured -- resuming normal operations
[Tue Aug 30 16:51:43.660358 2022] [core:notice] [pid 1:tid 281473523657800] AH00094: Command line: 'httpd -D FOREGROUND'

Running as:

/usr/local/apache2 $ whoami
www-data
  • Related