Docker: Run apache as non-root user based on the official image
Many docker images execute its main process as root but it’s not good for security reasons and it depends on Kubernetes cluster, Pod Security Policies is applied to avoid running containers as root. So, let’s take a look at how to run Apache Web Server as a non-root user.
Before trying, here is running the origin image without modifying.
1$ docker run -dt \
2--name my-app \
3--rm httpd:2.4
4
5$ docker exec -it my-app sh -c "apt update; apt upgrade -y; apt install -y procps; ps -aux"
6
7<installing>
8
9USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
10root 1 0.3 0.0 5940 4388 pts/0 Ss+ 03:48 0:00 httpd -DFOREGROUND
11daemon 8 0.0 0.1 1931504 11660 pts/0 Sl+ 03:48 0:00 httpd -DFOREGROUND
12daemon 9 0.0 0.1 1931504 11660 pts/0 Sl+ 03:48 0:00 httpd -DFOREGROUND
13daemon 10 0.0 0.1 1931504 11660 pts/0 Sl+ 03:48 0:00 httpd -DFOREGROUND
14root 92 0.1 0.0 2388 696 pts/1 Ss+ 03:48 0:00 sh -c apt update; apt upgrade -y;
15apt install -y procps; ps -aux
16root 409 0.0 0.0 7640 2676 pts/1 R+ 03:48 0:00 ps -aux
17
18$ docker stop my-app
As you see, the first process is executed as root and other sub processes run as "daemon" user. When executing the "docker run" command, all I need to do to run the container as some specified user is adding the "-u" option. However, if I add the option without any modification, the container cannot use port 80 because it’s permitted to root only as default. That’s why it’s necessary to use the "setcap" command to modify the linux capability. So, I created the following Dockerfile.
1FROM httpd:2.4
2
3RUN apt update \
4 && apt upgrade -y \
5 && apt install -y libcap2-bin procps \
6 && setcap 'cap_net_bind_service=+ep' /usr/local/apache2/bin/httpd \
7 && chown www-data:www-data /usr/local/apache2/logs
8
9USER www-data
In the above file, "procps" package is unnecessary for production. It’s just for verifying. And then, build the image.
1docker build -t non-root-apache .
After the building process, run a container.
1docker run -it --rm \
2--name my-apache-app \
3-p 8888:80 \
4-v `pwd`/www:/usr/local/apache2/htdocs \
5non-root-apache
After the container is up, open another terminal and test it via curl command.
1$ curl localhost:8888/test.txt
2hoge
The Apache’s log is also like this on the terminal as stdout.
1172.17.0.1 - - [22/Dec/2020:08:53:03 +0000] "GET /test.txt HTTP/1.1" 200 5
Just in case, check the result of ps command again.
1$ docker exec -it my-apache-app ps -aux
2USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
3www-data 1 0.0 0.0 5940 4244 pts/0 Ss+ 08:16 0:00 httpd -DFOREGROUND
4www-data 7 0.0 0.0 1931512 5420 pts/0 Sl+ 08:16 0:00 httpd -DFOREGROUND
5www-data 8 0.0 0.1 1931512 7516 pts/0 Sl+ 08:16 0:00 httpd -DFOREGROUND
6www-data 9 0.0 0.0 1931560 6060 pts/0 Sl+ 08:16 0:00 httpd -DFOREGROUND
7www-data 106 0.0 0.0 7640 2676 pts/1 Rs+ 08:54 0:00 ps -aux
As you see, all running processes are executed by the "www-data" user.