Docker: use non-root evcc user
@andig fixes #4850 Was wurde getan:
- ENV TZ removed (sollte mMn beim run übergeben werden)
- Runtime user default auf evcc geändert (adduser ...)
- /evcc Ordner als WORKDIR (kanm dann auch in der Doku als Mountpoint für persistierende Dateien übernommen werden)
- Entrypoint in /bin
- Auch docker-btmgmt in /bin (konnte aber nicht finden wofür das gut ist?)
- entrypoint ein wenig aufgeräumt. Es sei denn, dass was ich gelöscht hab, macht noch Sinn. Konnte es mir aber nicht erklären und aus Git-Log bin ich auch nicht schlau geworden
Refs https://github.com/evcc-io/evcc/pull/4901
Das macht einiges einfacher. thx
Das mit dem if [ "$1" in dem entrypoint Script ist so ähnlich in dem dockerfile best practices für entrypoint:
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypoint
Erstmal vielen Dank,. Ganz leicht über meinem üblichen shell-fu ;). Könntest du nochmal erklären, inwiefern das jetzt das uid/gid Problem löst? Ähnliches hätten wir ja auch mit dem guest user schnell und einfach (wenn auch nicht so schön) lösen können?
Bzgl. ENV: was passiert bei alpine wenn nix übergeben wird? Sollten wir das für den typischen CET Anwender nicht auf einen sinnvollen Default setzen? Otto Normalo wird keine Timezone von aussen setzen?
Das mit dem
if [ "$1"in dem entrypoint Script ist so ähnlich in dem dockerfile best practices für entrypoint:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypoint
Seems that is only done because it passes just not the parameter but not the actual binary as CMD. Not sure what the advantage of that is but seems its not necessary here.
Das mit dem
if [ "$1"in dem entrypoint Script ist so ähnlich in dem dockerfile best practices für entrypoint: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypointSeems that is only done because it passes just not the parameter but not the actual binary as
CMD. Not sure what the advantage of that is but seems its not necessary here.
Ich denke es geht darum, wie man Argumente an den cmd anhängen kann, also ob man docker run amdig\evcc evcc --help oder docker run andig\evcc --help machen muss.
Erstmal vielen Dank,. Ganz leicht über meinem üblichen shell-fu ;). Könntest du nochmal erklären, inwiefern das jetzt das uid/gid Problem löst? Ähnliches hätten wir ja auch mit dem guest user schnell und einfach (wenn auch nicht so schön) lösen können?
Du meinst das hier https://github.com/evcc-io/evcc/pull/4859/commits/d134836d576c8a9d74ff8c296e3f11019b58cac2 oder?
Da muss ich dir wohl Recht geben. Es ist tatsächlich ähnlich zu das, was du schon mal vorgeschlagen hattest. Zusätzlich setze ich nur 777 auf den /evcc-Ordner.
Ich habe etwas gegraben, wie Linuxserver das machen. Sie erzeugen den User im ENTRYPOINT-Script (sie benutzen allerdings s6) Das kann man auch hier tun. Allerdings bin ich deiner Meinung, dass das hier erstmals die "einfachere" Lösung ist.
Hier Link zu der Linuxserver-Lösung https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/s6-overlay/s6-rc.d/init-adduser/run
Das mit dem
if [ "$1"in dem entrypoint Script ist so ähnlich in dem dockerfile best practices für entrypoint: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypointSeems that is only done because it passes just not the parameter but not the actual binary as
CMD. Not sure what the advantage of that is but seems its not necessary here.Ich denke es geht darum, wie man Argumente an den cmd anhängen kann, also ob man
docker run amdig\evcc evcc --helpoderdocker run andig\evcc --helpmachen muss.
Ja, und? Spielt doch hier keine Rolle, oder?
Bzgl. ENV: was passiert bei alpine wenn nix übergeben wird? Sollten wir das für den typischen CET Anwender nicht auf einen sinnvollen Default setzen? Otto Normalo wird keine Timezone von aussen setzen?
Auch hier richtig. Allerdings würde ich das eher in der Doku eintragen (docker run -e TZ=...)
Erstmal vielen Dank,. Ganz leicht über meinem üblichen shell-fu ;). Könntest du nochmal erklären, inwiefern das jetzt das uid/gid Problem löst? Ähnliches hätten wir ja auch mit dem guest user schnell und einfach (wenn auch nicht so schön) lösen können?
Du meinst das hier d134836 oder? Da muss ich dir wohl Recht geben. Es ist tatsächlich ähnlich zu das, was du schon mal vorgeschlagen hattest. Zusätzlich setze ich nur 777 auf den
/evcc-Ordner.Ich habe etwas gegraben, wie Linuxserver das machen. Sie erzeugen den User im
ENTRYPOINT-Script (sie benutzen allerdings s6) Das kann man auch hier tun. Allerdings bin ich deiner Meinung, dass das hier erstmals die "einfachere" Lösung ist. Hier Link zu der Linuxserver-Lösung https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/s6-overlay/s6-rc.d/init-adduser/run
Dann verstehe ich das, danke. Plus du nutzt nicht /home/evcc sondern generierst ein eigenes, weiteres. Gehupft wie gesprungen, oder bewirkt das noch mehr? Optisch ist /evcc vielleicht leichter zu mounten als /home/evcc?
Bzgl. ENV: was passiert bei alpine wenn nix übergeben wird? Sollten wir das für den typischen CET Anwender nicht auf einen sinnvollen Default setzen? Otto Normalo wird keine Timezone von aussen setzen?
Auch hier richtig. Allerdings würde ich das eher in der Doku eintragen (docker run -e TZ=...)
Dann bitte Default. Es sind ja immer die gleichen Fragen im Support…
Erstmal vielen Dank,. Ganz leicht über meinem üblichen shell-fu ;). Könntest du nochmal erklären, inwiefern das jetzt das uid/gid Problem löst? Ähnliches hätten wir ja auch mit dem guest user schnell und einfach (wenn auch nicht so schön) lösen können?
Du meinst das hier d134836 oder? Da muss ich dir wohl Recht geben. Es ist tatsächlich ähnlich zu das, was du schon mal vorgeschlagen hattest. Zusätzlich setze ich nur 777 auf den
/evcc-Ordner. Ich habe etwas gegraben, wie Linuxserver das machen. Sie erzeugen den User imENTRYPOINT-Script (sie benutzen allerdings s6) Das kann man auch hier tun. Allerdings bin ich deiner Meinung, dass das hier erstmals die "einfachere" Lösung ist. Hier Link zu der Linuxserver-Lösung https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/s6-overlay/s6-rc.d/init-adduser/runDann verstehe ich das, danke. Plus du nutzt nicht /home/evcc sondern generierst ein eigenes, weiteres. Gehupft wie gesprungen, oder bewirkt das noch mehr? Optisch ist /evcc vielleicht leichter zu mounten als /home/evcc?
jap, ich habe etwas Schönheitsreparatur miteingeschleust :) Keine böse Absicht gehabt. Ich kann den /evcc zurückbauen, falls gewünscht
Das mit dem
if [ "$1"in dem entrypoint Script ist so ähnlich in dem dockerfile best practices für entrypoint: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypointSeems that is only done because it passes just not the parameter but not the actual binary as
CMD. Not sure what the advantage of that is but seems its not necessary here.Ich denke es geht darum, wie man Argumente an den cmd anhängen kann, also ob man
docker run amdig\evcc evcc --helpoderdocker run andig\evcc --helpmachen muss.Ja, und? Spielt doch hier keine Rolle, oder?
Ja, ist eine Geschmackssache, ob man die Verdoppelung von evcc in dem command vermeiden will. Habe gerade kurz auf die docs geschaut und dort nichts gesehen, wo das genutzt wird.
Bzgl. ENV: was passiert bei alpine wenn nix übergeben wird? Sollten wir das für den typischen CET Anwender nicht auf einen sinnvollen Default setzen? Otto Normalo wird keine Timezone von aussen setzen?
Auch hier richtig. Allerdings würde ich das eher in der Doku eintragen (docker run -e TZ=...)
Dann bitte Default. Es sind ja immer die gleichen Fragen im Support…
ENV TZ ist wieder drin
Leider wird gerade unter https://docs.evcc.io/docs/installation/docker#mit-docker-compose der entrypoint in der compose Datei auf /app/entrypoint.sh gesetzt. Wenn die Datei jetzt nicht mehr unter den Pfad zu finden ist, wird das bei einigen Nutzern beim Update zu einem Fehler führen:(
Leider wird gerade unter https://docs.evcc.io/docs/installation/docker#mit-docker-compose der entrypoint in der compose Datei auf
/app/entrypoint.shgesetzt. Wenn die Datei jetzt nicht mehr unter den Pfad zu finden ist, wird das bei einigen Nutzern beim Update zu einem Fehler führen:(
Stimmt. 3 Möglichkeiten:
- Doku anpassen
- Change zurückbauen
- Mit symlink probieren (und erst in einige Iterationen den Symlink löschen)
Der Konflikt mit der Docker Doku besteht doch darin, dass die ganz viel vollkommen unnützen Kram spezifiziert der eh Default ist. In meinen Augen ist das ein Bug, den können wir- auch wenn breaking- korrigieren.
Bzgl. entrypoint: was wir mit dem Change verlieren (war aber auch vorher nicht funktioniert hat) ist, dass wir nicht mehr
Docker run andig/evcc charger
Machen können. Es wäre schön, dieses Verhalten (zurück) zu bekommen. Dynamisch ginge das nur, wenn alle evcc sub commands berücksichtigt würden. Keine Ahnung wie sich das anstellen liesse?
@sveba und ich würde immer noch super gerne die uid/gid Geschichte verstehen.
Man muss zwischen HOST-User und Container-User unterscheiden. Der Container kennt die Benutzer vom Host nicht.
Der initiale Fehler bei mir war, dass ich den Docker-Container nicht mit einer anderen UID starten konnte, da die DB immer im HOME von root geschrieben wurde und der Ordner /root/.evcc nicht für alle RW gewesen war. Ich wollte das tun, da ich einen dedizierten HOST-Benutzer für Docker habe. Um dies zu beheben, konnte man den /root/.evcc einfach reinmounten und auf dem Host ihn RW für alle machen. Wäre schneller Fix.
Daraufhin habe ich die Lösung von Linuxserver vorgeschlagen. Die leider etwas mehr Aufwand bedeutet (und testing).
Dann war deine Idee, einen nonroot evcc-Benutzer im Container zu verwenden. Vollkommen richtig. Allerdings hätte das das Problem nicht gelöst, da der Ordner immernoch RW nur für den evcc-Container-Benutzer wäre. Deswegen habe ich in meinem PR einen /evcc-Ordner vorgestellt, der für alle RW ist und als Default-Storage für die DB genutzt wird. Egal mit welcher UID man den Container startet. Der Prozess wird aber mit einer UID gestartet, die nicht zu dem evcc-Container-Benutzer gehört! Der Container kennt diese UID nicht und kann sie zu keinem Container-Benutzer zuordnen. Deswegen sieht man bei einem ls innerhalb des Containers nur eine Zahl als File-Owner. Auch bei einem ps wäre der Owner unbekannt.
Die Linuxserver-Lösung bietet die Möglichkeit dem Container-User zur Laufzeit eine UID:GID zuzuweisen. Dafür wird im entrypoint der im Docker-Build angelegte Benutzer mit neuen UID:GID versehen. Dadurch kann man die UID:GID eines, auf dem HOST existierenden Nutzer beim run übergeben und alle Daten, die im Container geschrieben/erzeugt werden, kriegen die "richtige" GID:UID.
@andig Ich hoffe, das kann etwas helfen. Für weitere Fragen, oder falls der Wunsch besteht, dies Ähnlich wie bei Linuxserver zu tun, stehe ich zur Verfügung
In meinen Augen ist das ein Bug, den können wir- auch wenn breaking- korrigieren.
So sollte das besser passen: https://github.com/evcc-io/docs/pull/239
Die Linuxserver-Lösung bietet die Möglichkeit dem Container-User zur Laufzeit eine UID:GID zuzuweisen. Dafür wird im entrypoint der im Docker-Build angelegte Benutzer mit neuen UID:GID versehen. Dadurch kann man die UID:GID eines, auf dem HOST existierenden Nutzer beim run übergeben und alle Daten, die im Container geschrieben/erzeugt werden, kriegen die "richtige" GID:UID.
Genau, das muss ja zur Laufzeit sein. Hättest Du mal einen Link zu so einem entrypoint zum anschauen und vertehen wie das geht?
Ich hab bisher nur solche Dinge gefunden: https://nickjanetakis.com/blog/running-docker-containers-as-a-non-root-user-with-a-custom-uid-and-gid. Da passiert alles zur Buildzeit und das hat bei mir einfach nicht "klick" gemacht.
Hier Link zu der Linuxserver-Lösung https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/s6-overlay/s6-rc.d/init-adduser/run
@andig
Damit bleibt der letzte offene Punkt: schaffen wir es, dieses Pattern zu ermöglichen:
docker run andig/evcc charger
evcc hat ein completions Kommando- kann man das evtl. nutzen um die Liste der gültigen Werte zu ermitteln und die im entrypoint zu verarbeiten? Der status quo schaute ja bisher auch nur auf - was tatsächlich nicht hilft. Falls niemand eine Idee hätte mergen wir as-is.
@andig ist der letzte Commit was du meinst? Oder hab ich es falsch verstanden?
Im Prinzip ja... es gibt aber mehrere Szenarien:
- evcc (ohne Parameter)
- evcc -foo
- evcc charger|vehicle|...
aber auch
- /bin/sh
Ich fände es gut, wenn gerade der letzte case auch für interaktive Shell ginge ohne dass man mit --entrypoint rumdaddeln muss. Deshalb wäre es in Deinem PR perfekt, wenn wir den evcc Case einschränken könnten auf
- wenn erster Parameter eine Kommondozeilenoption ist (
-) oder - wenn erster Parameter ein evcc Subkommando ist
... und zwar ohne die Liste der Subkommandos statisch in der entrypoint.sh anlegen zu müssen. Wär das machbar?
Mit evcc __completeNoDesc "" bekommt man die liste der möglichen subcommands.
Mit
evcc __completeNoDesc ""bekommt man die liste der möglichen subcommands.
Top! Bekommen wir das (einschl. -) in eine Liste geparst und in der entrypoint.sh verarbeitet? Dann hätten wir die "Merzedes" Lösung :)
Meine 2 Cents
- evcc (ohne Parameter)
- evcc -foo
- evcc charger|vehicle|...
Alle 3 UseCases funktionieren.
Wegen /bin/sh - jeder der -it kennt wird auch --entrypoint kennen
Meine Meinung - macht es nicht komplizierter, als es sein soll :)
Wegen /bin/sh - jeder der -it kennt wird auch --entrypoint kennen
Da hast du auch wieder recht. Ich bin trotzdem noch nicht so recht glücklich:
- wir haben jetzt einen User mit /home/evcc als Directory
- die Datenbank schieben wir aber nach /evcc
- in https://github.com/evcc-io/evcc/pull/4901 wiederum landet die dann in /var/lib/evcc was auch als
homedirgenutzt wird
Wäre es nicht sinnvoll, die Strukturen gleich zu schneiden damits keine Verwirrung gibt?
/cc @goebelmeier bzgl. https://github.com/evcc-io/evcc/pull/4878#issuecomment-1288092213
Bekommen wir das hier irgendwie fertig? Brauchen wir wirklich unterschiedliche Hierarchien/User zwischen apt und Docker?