skip to Main Content

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


  1. 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 🙂

    Login or Signup to reply.
  2. Try to run this command in your Dockerfile

    RUN sed -i "s/Listen 80/Listen ${PORT:-8080}/g" /etc/apache2/ports.conf
    

    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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search