One of the things that you notice when using Docker, is that all commands you run from the
CMD are performed as the
root user. This is not only a bad security practice for running internet facing services, it might even prevent certain applications from working properly. So, how do you run commands as a non-root user? For people using Red Hat-based systems, such as Fedora or CentOS I will explain how you can do this.
Let's say you have a
Dockerfile using Fedora as a base:
Before we can use a different user, we need to create one:
RUN adduser user
Run as user
Now you can run commands as this user by doing:
RUN su - user -c "touch me"
The container start process can be changed to:
CMD ["su", "-", "user", "-c", "/bin/bash"]
This way, a
bash shell will open as the user.
Since you are running a normal user, it might be handy to install the following package inside the container:
RUN dnf install -y sudo
This will allow you to use
sudo to perform actions as the root user:
RUN echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \ chmod 0440 /etc/sudoers.d/user
To combine all of this, your
Dockerfile would look as follows:
FROM fedora:24 RUN dnf install -y sudo && \ adduser user && \ echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \ chmod 0440 /etc/sudoers.d/user RUN su - user -c "touch mine" CMD ["su", "-", "user", "-c", "/bin/bash"]
Building this container is simple:
$ docker build -t user . Step 1 : FROM fedora:24 ---> f9873d530588 Step 2 : RUN dnf install -y sudo && adduser user && echo "user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && chmod 0440 /etc/sudoers.d/user ---> Using cache ---> 05c3f3c7e9fc Step 3 : RUN su - user -c "touch me" ---> Running in 584ab0ad025b ---> 66ea558b9855 Removing intermediate container 584ab0ad025b Step 4 : CMD su - user -c /bin/bash ---> Running in 780e0ccd5f61 ---> b19a10012b28 Removing intermediate container 780e0ccd5f61 Successfully built b19a10012b28
Running it will produce the following result:
$ docker run -it --rm user [user@48add6313ab6 ~]$ ls -al total 20 drwx------ 2 user user 4096 Sep 8 08:51 . drwxr-xr-x 3 root root 4096 Sep 8 08:46 .. -rw-r--r-- 4 user user 18 May 17 14:22 .bash_logout -rw-r--r-- 4 user user 193 May 17 14:22 .bash_profile -rw-r--r-- 4 user user 231 May 17 14:22 .bashrc -rw-rw-r-- 1 user user 0 Sep 8 08:51 me [user@48add6313ab6 ~]$ pwd /home/user [user@48add6313ab6 ~]$
If you are setting up base images for re-use, it can be handy to use the
USER keyword. This will run all the following commqnds as a particalur. Lets say, you want to use a service, which is Node.JS based, you can create the following
FROM centos:7 MAINTAINER Gerard Braad <[email protected]> # Run update and install dependencies RUN yum update -y && yum install -y nodejs npm # Add the user UID:1000, GID:1000, home at /app RUN groupadd -r app -g 1000 && useradd -u 1000 -r -g app -m -d /app -s /sbin/nologin -c "App user" app && \ chmod 755 /app # Set the working directory to app home directory WORKDIR /app # Specify the user to execute all commands below USER app
You can then use this container as a base for NodeJS based applications. You copy the application to
/app and when commands are run, they will use the user named
I hope this has been of some help to you. You can follow me on Twitter or leave a comment below.