[Docker] Dockerfile RUN command after setting USER

palaber

Captain
Registriert
Juni 2006
Beiträge
3.856
Hallo zusammen,

ich versuche mich gerade an Docker. Und arbeite etwas mit dem Dockerfile.
Testweiße möchte ich eine React-App als Docker-Image erstellen. Ich halte mich dabei an ein Tutorial (codewithmosh).
Bis hier funktioniert alles wie es sollte.
Bash:
FROM node:16.20-alpine3.18
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
ENV API_URL=http://api.myapp.com
EXPOSE 3000
CMD ["npm start"]

Im Tutorial wird nun einen anderer User als den Root-User verwendet.
Macht Sinn. Laut Tutorial sollte das Dockerfile dann so aussehen:
Bash:
FROM node:16.20-alpine3.18
RUN addgroup app && adduser -S -G app app
USER app
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
ENV API_URL=http://api.myapp.com
EXPOSE 3000
CMD ["npm start"]

Ich bekomme dann aber beim erstellen des images mit "docker build..." beim Ausführen von "npm install" eine permission warning:
Error: EACCES: permission denied, open '/app/package-lock.json'
Habe jetzt soweit recherchiert, dass wohl meine WORKDIR keine permission für denuser "app" hat.
Es gibt wohl einen workaround mit --chown bei COPY, aber das klappt bei mir (noch) nicht.

1.) Hat jemand von euch eine Idee wie das geht? Vielleicht ein gutes Bsp.?

2.) Kann ich eigentlich nicht einfach den User nach den ganzen COPY Anweisungen setzten? Ob ich den build mit dem User root oder mit app oder was auch immer ausführe sollte doch egal sein, solange der Container nach dem Starten den app-User verwendet.
Bin mir aber nicht sicher, ob das wirklich ein guter Weg ist, da ich noch neu mit dem Thema bin.

Danke für eure Hilfe!
 
Ja, du kannst den USER Befehl einfach ganz unten hinmachen. Für gewöhnlich schreibe ich den unter oder über EXPOSE. CMD und ENTRYPOINT sind immer die letzten beiden bei mir.

Besser wäre auch so was wie multi-stage Dockerfiles zu nutzen, damit der Container nicht so riesig ist.
 
Danke @Skaro, ich bin eh der Meinung, dass das in dem Tutorial etwas seltsam ist.
In dem Forum wurde dann gesagt, dass man es wie folgt lösen kann:


Bash:
FROM node:16.20-alpine3.18
RUN addgroup app && adduser -S -G app app
USER app
WORKDIR /app
COPY --chown=app:app package*.json .
RUN npm install
COPY --chown=app:app . .
ENV API_URL=http://api.myapp.com
EXPOSE 3000
CMD ["npm start"]

Nur wenn ich das so mache, dann ist der app User ja der Ersteller von der Dir und dann ist der Benefit bezüglich Security wieder dahin.
Ergänzung ()

madmax2010 schrieb:
run chown user:grp file
aka
RUN chown -R node:node /app
ist das nicht das, was ich gerade auch gepostet habe und davon ausgegangen bin, dass ich damit dann die Berechtigung der Dir so setze, dass ich Dateien ändern kann? Was ich ja eigentlich als "User der die App nur betreibt" nicht möchte.
 
palaber schrieb:
Nur wenn ich das so mache, dann ist der app User ja der Ersteller von der Dir und dann ist der Benefit bezüglich Security wieder dahin.

ist das nicht das, was ich gerade auch gepostet habe und davon ausgegangen bin, dass ich damit dann die Berechtigung der Dir so setze, dass ich Dateien ändern kann? Was ich ja eigentlich als "User der die App nur betreibt" nicht möchte.
Warum? Der User soll natuerlich seine eigenen files bearbeiten koennen. Du nutzt einen anderen user als root in docker vor allem, damit falls dein container uebernommen wird und der angreifer es schafft aus dem container auszubrechen, er kein root auf dem system bekommt.
 
Also ich kann nur wiedergeben, was in dem Tutorial gesagt wurde:

"-S" erstellt einen system user, der nur dazu genutzt werden soll die Applikation laufen zu lassen
der app user "runs" die aktuelle session, er soll aber in the "other" group der permissions fallen
ansonsten könnte ein Angreifer potenziell Dinge in der App umschreiben

Mit dem Base Image aus dem Tutorial und nicht mit dem neusten Base Image geht übrigens alles.
Und die Permissions sehen dann aus wie folgt:
1687203413090.png

Mal sehen, ob ich das mit chown nachbauen kann.

Was du mit den root user meinst, verstehe ich nicht ganz. Wenn ein container eine isolierte Umgebung ist, was hat dann der root user mit dem root user des host-Systems zu tun?


Edit:
Wenn ich das Skript wie folgt umbaue, dann sind die Berechtigungen wie im Tutorial auch. Damit gebe ich mich zufrieden :)

1687206101366.png
 
Zuletzt bearbeitet:
palaber schrieb:
Was du mit den root user meinst, verstehe ich nicht ganz. Wenn ein container eine isolierte Umgebung ist, was hat dann der root user mit dem root user des host-Systems zu tun?
Lies mal nach wie Docker, bzw Containerd und Linux Container funktionieren. Es ist vereinfacht gesagt einfach ein Prozess, der durch Kernel Features isoliert wird. Aber es bleibt ein einfacher Prozess. Wenn du einen Container startest und du mit z.B. htop schaust, siehst du, dass einfach ein Prozess läuft, der den User hat, den du für den Container angegeben hast, wenn du keinen angegeben hast und Docker nutzt, ist das Root. Und das ist dann wirklich der Root User der Maschine. Wenn ein Angreifer also deinen Container übernimmt und eine Möglichkeit über z.B. eine Sicherheitslücke im Kernel auszubrechen, ist er der User, mit dem der Prozess läuft.

Weitere Schutzmaßnahmen innerhalb des Containers, z.B. dem Prozess nur lesenden Zugriff auf den Code zu geben kannst du machen, in der Regel ist es aber komplizierter und du nicht immer relevant. Oft will ein Angreifer ja einfach entweder irgendwelchen Code ausführen, den er selber mitbringt oder Daten auslesen. Beides geht auch, wenn er den Code deiner Anwendung nicht verändern kann.
 
@palaber
Wie zufrieden bist du mit den Courses von Mosh? Im Forum wird bemängelt das sie nicht so Up-to-date sind.
 
@sh. Ich mag die Kurse von Mosh, weil ich ihm sehr gut folgen kann und ich es ganz gut verstehe, was er erklärt. Hatte schon ab und an das Problem, dass aufgrund von Versionsänderungen Dinge nicht mehr funktioniert haben. Bisher konnte ich aber immer eine Lösung finden. Häufig auch im dazugehörigen Forum.
Ggfs. gibt es Coaches, die ihren Stoff aktueller halten. Dazu kann ich aber nicht viel sagen. ;)
Um einen Einstieg zu erhalten, finde ich sie auf jeden Fall gut bis sehr gut.

NJay schrieb:
Lies mal nach wie Docker, bzw Containerd und Linux Container funktionieren. Es ist vereinfacht gesagt einfach ein Prozess, der durch Kernel Features isoliert wird. Aber es bleibt ein einfacher Prozess. Wenn du einen Container startest und du mit z.B. htop schaust, siehst du, dass einfach ein Prozess läuft, der den User hat, den du für den Container angegeben hast, wenn du keinen angegeben hast und Docker nutzt, ist das Root. Und das ist dann wirklich der Root User der Maschine. Wenn ein Angreifer also deinen Container übernimmt und eine Möglichkeit über z.B. eine Sicherheitslücke im Kernel auszubrechen, ist er der User, mit dem der Prozess läuft.
Bin ja ein Docker Anfänger :) - Aber das ein Container ein Prozess ist, hat auch Mosh mir mitgeteilt. Wenn ich innerhalb meines Demo-Containers whoami ausführe (siehe Bild oben) wird der User "app" angezeigt und nicht "root". Das war das, worauf meine Frage bezogen war. Damit sollte der Container doch abgesichert sein um nicht direkt den root im host-system zu benutzen?!?
 
  • Gefällt mir
Reaktionen: sh.
palaber schrieb:
Bin ja ein Docker Anfänger :) - Aber das ein Container ein Prozess ist, hat auch Mosh mir mitgeteilt. Wenn ich innerhalb meines Demo-Containers whoami ausführe (siehe Bild oben) wird der User "app" angezeigt und nicht "root". Das war das, worauf meine Frage bezogen war. Damit sollte der Container doch abgesichert sein um nicht direkt den root im host-system zu benutzen?!?
Ja in deinem Fall haette ein Angreifer wenn er aus dem Container ausbricht dann nicht direkt root zugriff.

Aber diese ganze thematik spielt auch immer nur dann eine Rolle, wenn es eine Sicherheitsluecke in Docker/containerd, etc gibt, die es erlaubt aus dem container auszubrechen, Im standard sollte das nicht passieren. Ist einfach eine absicherung mehr.
 
  • Gefällt mir
Reaktionen: madmax2010
Zurück
Oben