I’ve built a docker image based on httpd:2.4. In my k8s deployment I’ve defined the following securityContext
:
securityContext:
privileged: false
runAsNonRoot: true
runAsUser: 431
allowPrivilegeEscalation: false
When I apply the deployment without this securityContext
everything works fine, the server starts up correctly, etc. However when I add in the above securityContext
my pod has the status CrashLoopBackOff
and I get the following from $ kubectl logs...
(13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs
From searching around online I’ve found that this is because apache needs to be root in order to run, so running as non-root will fail.
I’ve also found that httpd.conf
has the following
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User daemon
Group daemon
Which seems to suggest that if I don’t use runAsNonRoot
or runAsUser
in securityContext
it should automatically switch to whichever user I specify in httpd.conf
. In my case I created a user/group swuser
and edited httpd.conf
accordingly. However when I run the image locally with docker run -p 5000:80 my-registry/my-image:1.0.12-alpha
and then run docker exec -it my-container whoami
it prints root
.
So my question is, what can I do to run my container safely as non-root in k8s (and be sure it is non-root)
2
Answers
Run the apache on a port greater than 1024.
Ports below 1024 are privileged ports only available to the root user.
As you will have some ingress load balancer before that, it shouldn’t matter 🙂
Try to run this command in your Dockerfile
This command is a Dockerfile instruction that runs a sed command to replace the default Listen 80 configuration in the /etc/apache2/ports.conf file with a specified port number. Here’s a breakdown of the command:
RUN is a Dockerfile instruction that allows you to run commands inside the container during the build process.
sed is a command-line utility that is used to edit files in-place using regular expressions.
-i flag tells sed to modify the file in-place, meaning the original file will be overwritten with the changes.
"s/Listen 80/Listen ${PORT:-8080}/g" is a regular expression used by sed to find and replace the Listen 80 string with the value of the ${PORT} environment variable or the default value 8080 if ${PORT} is not set.
/etc/apache2/ports.conf is the path to the file to be edited by sed.
The command can be interpreted as follows: "During the Docker image build process, replace the default Apache web server port Listen 80 with the port number specified in the ${PORT} environment variable. If ${PORT} is not set, use the default port number 8080. This is done by running the sed command to edit the /etc/apache2/ports.conf file."
This command is commonly used in Dockerfiles for web applications that run on a specific port, allowing the user to define the port number during runtime via an environment variable.
You can see and edit your command with explainshell.com
Command details on explaishell