Running containers such as non-root is one of the most popular best practices for security.
This approach prevents malicious code from gaining permissions in the container host. It also allows running containers on Kubernetes distributions that don’t allow running containers as root, such as OpenShift. For more information about the reasons to use a non-root container, check these blog posts:
To convert the Docker image into a non-root container, change the default user from root
to nonroot
:
...
EXPOSE 80
+ useradd -r -u 1001 -g nonroot root
+ USER nonroot
CMD ["node", "/app/server.js"]
...
Tip
Add the nonroot
user to the root
group.
Take these details into consideration when moving a container to non-root:
File permissions: What directories should be writable by the application? Adapt them by giving writing permissions to the non-root users. Check Linux Wiki for more information about changing permissions.
Port access: You cannot use privileged (1-1023) ports anymore.
Debugging: You cannot perform any action that requires privileged permissions for debugging purposes.
Tip
It is important to understand that you should not move a container to a non-root approach and then use sudo
to gain higher-lever privileges, as this defeats the purpose of using a non-root approach. Similarly, you should also ensure that the non-root user account is not part of the sudoers group, to maximize security and avoid any risk of it obtaining root privileges.
Our sample application uses port 80
to listen for connections. Adapt it to use an alternative port such as 8080
:
Dockerfile:
... COPY --from=builder /tiller-proxy /proxy - EXPOSE 80 + EXPOSE 8080 RUN useradd -r -u 1001 -g root nonroot ...
server.js:
... const serverHost = '127.0.0.1'; - const serverPort = 80; + const serverPort = 8080; ...
On the other hand, the application writes its log in the /var/log/app.log file. Give permissions to the nonroot
user on that directory:
...
RUN useradd -r -u 1001 -g root nonroot
EXPOSE 80
+ RUN chmod -R g+rwX /var/log
USER nonroot
...
Test it:
$ docker build . -t express-image:0.0.7
$ docker run --rm -p 8080:8080 -d express-image:0.0.7
$ curl http://127.0.0.1:8080
Hello world
$ docker exec express-app whoami
nonroot
$ docker stop express-app
As you can see, everything is working as expected and now your container is not running as root
anymore.