Bash Dockerfile: Anweisung nach Mount und vor CMD möglich?

CyborgBeta

Banned
Registriert
Jan. 2021
Beiträge
3.958
Hallo,

mein Dockerfile sieht strukturell so aus:

Bash:
FROM debian:12

ENV TZ=Europe/Berlin

EXPOSE ...

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update
RUN apt upgrade -y
RUN apt install ... -y

RUN adduser --disabled-password --gecos "" headless
RUN echo "root:no"|chpasswd

RUN apt clean

USER headless
WORKDIR /home/headless
RUN git -C noVNC pull || git clone https://github.com/novnc/noVNC.git noVNC

CMD ...

Das Problem ist Zeile 19. Wenn es den Ordner noVNC noch nicht gibt, soll gecloned werden, ansonsten nur gepulled. (Diese RUN-Anweisung sollte eigentlich semantisch richtig sein.)

Das Verzeichnis /home/headless wird aber durch docker compose erst später gemountet (nach dem RUN). Sprich, ich gehe davon aus, dass das Clone bzw. Pull zurzeit keinen Effekt hat.

Darf ein Dockerfile mehrere CMD-Anweisungen haben, oder wie umgehe ich den Schlamassel?

Ich weiß leider auch nicht, ob der Container beim Mounten Sklave ist oder nicht. Vermutlich wird der Host immer als Master fungieren.

Tipps?
 
Eine gängige Lösung für solche Szenarien ist es, ein entsprechendes Bash-Skript mit mit der nötigen Logik zu schreiben, dieses ins Image zu integrieren und dann statt der ganzen Einzelbefehle aufzurufen.

Edit: gerade bemerkt, dass es ja ums Bauen des Images geht.
 
noVNC soll ja persistiert werden. Sprich, es soll Rebuilds überstehen.
 
Sowas ist aber meiner Meinung nach nicht die Aufgabe eines Images bzw. dessen Buildprozesses.
 
  • Gefällt mir
Reaktionen: wirelessy
Das passiert beim Initial-Build:

docker compose build --no-cache --progress plain novnc-debian

Code:
#16 [novnc-debian 13/13] RUN git -C noVNC pull || git clone https://github.com/novnc/noVNC.git noVNC
#16 0.365 fatal: cannot change to 'noVNC': No such file or directory
#16 0.366 Cloning into 'noVNC'...
#16 DONE 1.4s

Das passiert beim Rebuild:

docker compose build --progress plain novnc-debian

Code:
#16 [novnc-debian 13/13] RUN git -C noVNC pull || git clone https://github.com/novnc/noVNC.git noVNC
#16 CACHED
Ergänzung ()

mibbio schrieb:
nicht die Aufgabe eines Images bzw. dessen Buildprozesses.
Nein? Wo soll das sonst geschehen?
 
CyborgBeta schrieb:
Nein? Wo soll das sonst geschehen?
Alles was du persistieren willst, solltest du in "das" Docker-Filesystem packen.

Alles womit du arbeiten willst, kannst du dann bequem in andere Verzeichnisse mounten. Dein "philosophischer Fehler" ist also, dass du dein git pull in ein "Arbeitsverzeichnis", statt in ein persistentes machen willst.
 
Wohoo, so funktioniert es:

Bash:
USER headless
WORKDIR /home/headless

CMD [ "sh", "-c", "cd /home/headless/ \
&& (if cd noVNC; then git pull; else git clone https://github.com/novnc/noVNC.git noVNC; fi) \
&& cd /home/headless/ \
&& rm -rfv /tmp/.X1* \
&& tigervncserver -localhost yes -SecurityTypes None -geometry 1600x900 -autokill \
&& cd noVNC/ && (nohup ./utils/novnc_proxy --vnc localhost:5901 --listen 6901 &) \
&& trap 'tigervncserver -kill :*; exit' INT; echo waiting; while : ; do sleep 1 ; done" ]

Möglicherweise funktioniert es auch ohne die absoluten Pfade, das hab ich jetzt nicht ausprobiert.
Ergänzung ()

stefan92x schrieb:
Dein "philosophischer Fehler" ist also, dass du dein git pull in ein "Arbeitsverzeichnis", statt in ein persistentes machen willst.
Das Arbeitsverzeichnis ist doch persistent.
 
Ja, es geht.

Insgesamt habe ich jetzt:

Bash:
FROM debian:12

ENV TZ=Europe/Berlin

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update
RUN apt upgrade -y
RUN apt install nano net-tools git -y

RUN adduser --disabled-password --gecos "" headless
RUN echo "root:no"|chpasswd

RUN apt install <...> -y

RUN apt clean

CMD [ "sh", "-c", "(if cd noVNC; then git pull; else git clone https://github.com/novnc/noVNC.git noVNC; fi) \
&& cd ~ \
&& <...>" ]

Der Trick war, die Anweisung in das CMD zu verschieben.

Das EXPOSE war überflüssig.

Den Rest regelt dann docker compose bzw. traefik sichert ab:

Code:
  novnc-debian:
    build: ./novnc-debian
    init: true
    stop_signal: SIGINT
    user: 1000:1000
    volumes: <...>
Ergänzung ()

Bitopium schrieb:
Das nennt man cachen
Stimmt, war kein Rebuild.

Bitopium schrieb:
Und das ist was fundamental Anderes als zur docker build Zeit
Das stimmt. Es kommt in meinem Fall aber aufs Gleiche heraus, wenn ich den Container neu starte, dann soll sich das Teil die Updates ziehen.
 
Zuletzt bearbeitet:
CyborgBeta schrieb:
Der Trick war, die Anweisung in das CMD zu verschieben.
Das CMD wird aber eben nicht beim Build ausgeführt, sondern beim Starten eines entsprechenden Containers.

The CMD instruction sets the command to be executed when running a container from an image.
https://docs.docker.com/reference/dockerfile/#cmd

Das Ergebnis des Befehls bzw. deiner Befehlskette wird also nicht Teil des Images, sondern ist im Dateisystem des gestarteten Containers. Wird der Container beendet (und gelöscht), ist auch wieder alles weg, was der Befehl erzeugt hat. Außer es liegt in einem persistenten Volume, welches man wiederverwendet.

Und bei der Gelegenheit verweise ich auch mal auf meine erste Antwort. Es ist eigentlich Best Practice, im CMD nicht endlos Befehle zu verketten. Stattdessen schreibt man sich ein Skript, bspw. "startup.sh", mit den ganzen notwendigen Befehlen, baut dieses dann ins Image mit ein und gibt bei CMD oder ENTRYPOINT das Skript an.
 
  • Gefällt mir
Reaktionen: CyborgBeta
Danke, ja, das siehst du richtig. Die CMD-Anweisung läuft bei mir inzwischen etwas aus dem Ruder.

Ich wollte es von der Komplexität her aber möglichst einfach halten ... Wenn es ginge, hätte ich auch alles ins docker-compose.yml file gepackt.
 
Es funktioniert auch mit Debian/KDE unter Windows. Dadurch braucht man vmware oder virtual box nicht mehr installieren.

Schritte:

Erstelle einen Ordner debian irgendwo mit drei Dateien:

debian/Dockerfile:
Code:
FROM debian:12

ENV TZ=Europe/Berlin

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt update
RUN apt upgrade -y
RUN apt install nano net-tools git -y
RUN apt install kde-standard -y
RUN apt install task-kde-desktop -y
RUN apt install tigervnc-standalone-server dbus-x11 -y
RUN apt clean

RUN adduser --disabled-password --gecos "" cb
RUN echo "root:no"|chpasswd

USER cb
WORKDIR /home/cb

CMD [ "sh", "-c", "(if cd noVNC; then git pull; else git clone https://github.com/novnc/noVNC.git noVNC; fi) \
&& cd ~ \
&& rm -rfv /tmp/.X1* \
&& tigervncserver -localhost yes -SecurityTypes None -geometry 1600x900 -autokill \
&& cd noVNC/ && (nohup ./utils/novnc_proxy --vnc localhost:5901 --listen 6901 &) \
&& trap 'tigervncserver -kill :*; exit' INT; echo waiting; while : ; do sleep 1 ; done" ]

debian/docker-compose.yml:
Code:
services:
  debian-novnc:
    build: ./
    init: true
    stop_signal: SIGINT
    user: 1000:1000
    volumes:
      - ./data1/:/home/cb/
    ports:
      - 127.0.0.1:6901:6901

Erstelle einen leeren Ordner debian/data1.

Starten:

docker compose up und paar Minuten warten. Danach http://localhost:6901 aufrufen.

Stoppen:

Strg+C und kurz warten. Herunterfahren des Desktops nicht notwendig.

Ergebnis:

1739092162545.png


Wichtig:

Macht Port 6901 nicht über das www zugängig, da nicht verschlüsselt, kein Passwort und so.

Verwendung:

su mit Passwort no funktioniert. sudo würde funktionieren, wenn man den Benutzer der sudo-Gruppe hinzufügt.

Installiert Pakete nach - oder was auch immer ihr wollt.

Was ich noch nicht herausgefunden habe, ist, wie Docker den RAM und die CPU zuweist. Aber offenbar steht die Hälfte des RAMs des Hosts zur Verfügung.

Hope this helps.
Ergänzung ()

Edit: Noch wichtig, als root einmal passwd -d cb aufrufen, ansonsten sperrt ihr euch aus, sobald der KDE Bildschirmschoner an geht.
 
Zuletzt bearbeitet:
Zurück
Oben