Docker Best Practice – Prozess als nicht Root-Benutzer ausführen

Docker_Best_Practice

Docker Container werden mittlerweile an den unterschiedlichsten Stellen eingesetzt. Es gibt unzählige Use Cases in den Bereichen der Softwareentwicklung und des späteren Betriebs der Programme. Unter anderem auch deswegen, weil es recht einfach ist, ein eigenes Dockerfile zu schreiben, um ein an seine eigenen Bedürfnisse angepasstes Docker Image zu erhalten. Ein Blick in die offizielle Dokumentation lässt aber erahnen, wie umfangreich die Möglichkeiten beim Schreiben eines Dockerfile sind.


Obacht, denn ...

... "Aus großer Kraft folgt große Verantwortung". Will sagen, dass man durch die umfangreichen Möglichkeiten auch viele Gelegenheiten hat, etwas falsch zu machen. Glücklicherweise gibt es unzählige Best Practices im Internet zu finden, die viele Vorgehensweisen beschreiben, die man bei der Definition eines Dockerfile übernehmen sollte. Auch hier hilft die offizielle Dokumentation mit verschiedenen Artikeln aus. Im Nachfolgenden werden wir uns das Beispiel des offiziellen Tomcat Docker Images genauer anschauen und untersuchen. Denn wie im Titel schon angedeutet, möchte ich einen etablierten Best Practice anhand dieses Tomcat Images verdeutlichen.

Mit dem Start des Tomcat Images würde auch eine enthaltene Applikation (war-Datei) hochfahren und einen Dienst zur Verfügung stellen. Im Container läuft also ein Linux-Prozess des Tomcats.
Unabhängig von Docker hat ein Prozess unter Linux die Eigenschaft, dass dieser in einen klar beschriebenen Kontext läuft. Dieser Kontext definiert sich unter anderem dadurch, welcher Benutzer den Prozess gestartet hat. Im Standardfall wird der Prozess im Container von root gestartet.

Mit dem folgenden Befehl starten wir den Container:



docker run --name tomcat -d tomcat:9-jdk15-openjdk-buster 

Wo ist das Problem?

Auf dem ersten Blick ist alles in Ordnung. Der Container startet durch die Angabe mit -d im Hintergrund. Mit dem nächsten Befehl können wir überprüfen, welche Prozesse im Container laufen.

docker exec -it tomcat ps -ef
# Ausgabe:
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  1 14:39 ?        00:00:05 /usr/local/openjdk-15/bin/java - 

Die Spalte UID gibt an, mit welchem User der Prozess gestartet wurde. Wie erwartet finden wir hier die Angabe des root-Benutzers.

Allerdings entspricht es nicht der feinen englischen Art einen Prozess als root auszuführen. Ein Prozess sollte mit so wenig Rechten ausgestattet sein, wie nur unbedingt notwendig. Dieser Best Practice ist wesentlich älter als Docker selbst. Die Gründe dazu würden den Umfang dieses Posts sprengen. Allerdings versuche ich diese Lehrmeinung in einer lakonische Aussage zu verdichten.

Weniger Rechte, mehr Sicherheit.

nach Maik Krawinkel
Je weniger Rechte ein Benutzer hat, desto weniger kann dieser kaputt machen und somit Schaden anrichten. Die Schlussfolgerung ist also schnell gezogen. Der Tomcat Prozess im Docker Container sollte ebenfalls nicht mit root-Rechten laufen. Der nachfolgende Auszug aus einem Dockerfile zeigt auf, wie wir das erreichen können.
In den Zeilen 35 erzeugen wir einen neuen Benutzer und eine Gruppe mit dem Namen java. Dieser Benuzter hat weitaus weniger Rechte als der root-Benutzer. Zusätzlich besitzt dieser neue Benutzer das Verzeichnis, in dem sich der Tomcat befindet. Mit der Angabe in Zeile 7 werden nachfolgende Befehle, also auch der Start des Tomcats, durch den java-Benutzer ausgeführt. Zeile 9 zeigt, wie man eine zuvor gebaute Applikation in das Deployment-Verzeichnis des Tomcats kopieren kann. Der Besitzer dieser Datei ist durch die --chown Angabe der java-Benutzer.
FROM tomcat:9-jdk15-openjdk-buster

RUN groupadd -r java && \
    useradd -r -s /bin/false -g java java && \
    chown -R java:java /usr/local/tomcat

USER java

COPY --chown=java:java <WAR_DATEI_AUF_DEM_HOST> /usr/local/tomcat/webapps/app.war 

Als nächstes müssen wir das Image bauen und testen, ob alles geklappt hat. Sofort ist ersichtlich, dass der Prozess nun nicht durch den root-Benutzer gestartet wurde. Das Ziel ist erreicht. Der Tomcat-Prozess läuft nicht mehr mit weitreichenden Rechten, die den root-User auszeichnen.

docker build -t tomcat-ohne-root .
docker run --name tomcat-ohne-root -d tomcat-ohne-root
docker exec -it tomcat-ohne-root ps -ef
# Ausgabe:
UID        PID  PPID  C STIME TTY          TIME CMD
java         1     0 66 15:17 ?        00:00:04 /usr/local/openjdk-15/bin/java - 
In diesen Artikel habe ich einen einzelnen Best Practice aufgezeigt. Aber es gibt noch viel mehr zu beachten und zu lernen. In Zukunft werden weitere Artikel zu diesem Thema hier im Blog veröffentlicht. Seid also gespannt :-)

By accepting you will be accessing a service provided by a third-party external to https://blog.ordix.de/