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:
- Run Apache as the
www-data
user - Grant the
www-data
user the ability to bind to privileged ports, and - 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