# Docker getting started Im ersten Teil geht es darum, ein Docker image zu erstellen und im zweiten darum dieses auszuführen. ## Image erstellen Es gibt mehrere Methoden ein Docker Image zu erstellen. Man fängt aber immer damit an eine *Dockerfile* zu erstellen. ### Auswahl des Basis-Images Nun öffnen wir die Dockerfile und wählen ein Basis-Image aus. Das Basis-Image kann beliebig sein und darauf baut dann das Image auf. Beispiele für solch ein Basis-Image kann z.B. sein: - Ubuntu: ```ubuntu``` - Debian: ```debian``` - CentOS: ```centos``` - Alpine Linux: ```alpine``` - Fedora: ```fedora``` - OpenSUSE: ```opensuse``` - Oracle Linux: ```oraclelinux``` - Windows Server Core: ```mcr.microsoft.com/windows/servercore``` - Windows Nano Server: ```mcr.microsoft.com/windows/nanoserver``` - Webserver: - NGINX: ```nginx``` - Apache HTTP Server: ```httpd``` - Node.js: ```node``` - Python: ```python``` - Ruby: ```ruby``` - Datenbanken: - MySQL: ```mysql``` - PostgresSQL: ```postgres``` - MongoDB: ```mongo``` - Redis: ```redis``` - MariaDB: ```mariadb``` - Weitere Anwendungen: - Java: ```openjdk``` - PHP: ```php``` - Go: ```golang``` - .NET Core: ```mcr.microsoft.com/dotnet/core/sdk``` - WordPress: ```wordpress``` - Django: ```django``` So nutzt man z.B. ein Image in der *Dockerfile*: ```dockerfile FROM ubuntu:latest ``` ### Hinzufügen von Anweisungen nachdem in der ersten Zeile unser verwendetes Basis-Image steht werden wir uns nun den gängigsten Anweisungen widmen, welche wir nutzen, um das Image zu konfigurieren und Daten oder Anwendungen hinzuzufügen. Hier sind die gängigsten Anweisungen: - ```RUN```: Führt Befehle aus, um Pakete zu installieren oder Anwendungen innerhalb des Images zu konfigurieren. - ```COPY```: Kopiert Dateien oder Verzeichnisse vom Host in das Image. - ```ADD```: Ähnlich wie COPY, kann aber auch URLs und TAR-Archive verarbeiten. - ```ENV```: Setzt Umgebungsvariablen innerhalb des Images. - ```EXPOSE```: Gibt an, auf welchem Port die Anwendung in dem Container lauscht. - ```CMD```: Definiert den Befehl, der ausgeführt wird, wenn der Container gestartet wird. - ```ENTRYPOINT```: Gibt den ausführbaren Befehl oder das Skript an, das beim Start des Containers ausgeführt wird. Nun können wir z.B. git in unser Image installieren, nachdem der Container gestartet worden ist: ```dockerfile FROM ubuntu:latest # Git installieren RUN apt-get update && apt-get install -y git ``` Danach können wir die *bash* starten damit sich die Konsole öffnet: ```dockerfile FROM ubuntu:latest # Git installieren RUN apt-get update && apt-get install -y git # Arbeitsverzeichnis ENTRYPOINT [ "bash" ] ``` ___Note:___ Der ```ENTRYPOINT``` ist das erste auszuführende Skript im Container! Nun können das Image etwas weiter ausbauen und z.B. Stable Diffusion von *AUTOMATIC1111* herunterladen und ausführen: ```dockerfile # Verwende das offizielle Ubuntu-Basisimage mit dem Tag "latest" FROM ubuntu:latest # Aktualisiere das Paket-Repository und installiere Git RUN apt-get update && apt-get install -y git # Lege das Arbeitsverzeichnis im Container fest WORKDIR /app # Klone das Git-Repository in das Arbeitsverzeichnis im Container RUN git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git /app # Navigiere in den Ordner des Git-Repositories WORKDIR /app/stable-diffusion-webui # Führe das Shell-Skript "webui.sh" aus CMD ["/app/webui.sh"] ``` Dies war natürlich ein naiver Ansatz, denn so müssen wir auch beachten, was wir später in unserer ausführbaren Datei brauchen. ⚠️Wenn wir das Programm mithilfe von einer GPU ausführen lassen wollen brauchen wir *nvidia-docker*. Das muss aber auf dem Host-System installiert werden. ⚠️ So sieht nun schlussendlich unsere fertige Dockerfile aus: ```dockerfile # Verwende das offizielle Ubuntu-Basisimage mit dem Tag "latest" FROM ubuntu:latest # Aktualisiere das Paket-Repository und installiere Git und Python 3 RUN apt-get update && apt-get install -y git python3 python3.10-venv # Installiere die erforderlichen NVIDIA-Bibliotheken und -Treiber innerhalb des Containers RUN apt-get install -y nvidia-cuda-toolkit # Lege das Arbeitsverzeichnis im Container fest WORKDIR /app # Klone das Git-Repository in das Arbeitsverzeichnis im Container RUN git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git /app/stable-diffusion-webui # Navigiere in den Ordner des Git-Repositories WORKDIR /app/stable-diffusion-webui # Erstelle einen neuen Benutzer "sduser" im Container RUN useradd -ms /bin/bash sduser # Ändere den Besitzer des Arbeitsverzeichnisses auf den Benutzer "sduser" RUN chown -R sduser:sduser /app # Wechsle zum Benutzer "sduser" USER sduser # Lege einen *temporären* Argument an, damit NUR die CPU benutzt wird ENV COMMANDLINE_ARGS="--use-cpu all --skip-torch-cuda-test --precision full --no-half --listen" # Führe das Shell-Skript "webui.sh" aus CMD ["bash", "/app/stable-diffusion-webui/webui.sh"] ``` Beachte aber das hier die GPU NICHT mit eingebunden worden ist, da die Flag: ```--skip-torch-cuda-test``` gesetzt worden ist. Die weiteren Flags sind da um die Probleme mit einer nicht vorhanden GPU zu beheben. Diese sollten auch entfernt werden, sobald man eine GPU benutzen will. ❗ Wenn die GPU funktioniert startet man den Container später mit dem flag ```--gpus all```. Hier sind alle Flags, welche man bei Stable Diffusion WebUI verwenden kann (von AUTOMATIC1111):
[Command Line Arguments and Settings](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings) ## Container aus dem Image erstellen Navigiere in den Ordner wo die *Dockerfile* liegt und baue das Image. Mit unserem vorherigen Beispiel sähe der Befehl nun z.B. so aus: ``` docker build -t stablediffown . ``` ⚠️ Beachte jedoch das Docker dafür gestartet sein muss. ⚠️ Mit dem ```-t```-Flag kann man einem Image einen benutzerdefinierten Namen geben. Anschließend kann man überprüfen, ob das Image erstellt worden ist: ``` docker images ``` Hier sollte normalerweise das aktuelle Image angezeigt werden. ## Erstmaliges starten des Containers Starte nun den Container und gebe diesen Container einen Namen, wenn dies gewünscht ist. Gleichzeitig konfiguriere den Container. Also Portweiterleitung, etc. . Hier sind mehrere Konfigurationsmöglichkeiten: - mit GPU-Support (--gpus) - mit Namensgebung (--name) - mit Portweiterleitung (-p) - mit einem Volumen zur permanenten Datenspeicherung (-v) - mit Aufrechterhalten der Konsole (-it) ``` docker run --gpus all -p PORT_AUF_HOST:PORT_IM_CONTAINER -v /pfad/auf/host:/pfad/im/container -it my_image_name ``` Man kann sowohl relative Pfade als auch absolute Pfade verwenden.
Relative Pfade:
```./verzeichnis/auf/...```
Absolute Pfade:
```/verzeichnis/auf/...```
⚠️ Die Ordner müssen auf dem Host System existieren. ⚠️
Die relativen Pfade gelten immer von dort aus wo der Befehl ```docker run``` ausgeführt wird. Falls manche Ordner im Container noch nicht existieren sollten werden diese automatisch angelegt. Ohne GPU: ``` docker run --name MeinEigenerContainer -p 7860:7860 -it stablediffown ``` Mit GPU: ``` docker run --name MeinEigenerContainer --gpus all -p 7860:7860 -it stablediffown ``` *Finaler Command beim erstmaligen Starten des Containers **ohne** GPU:*
Hier wird nun der Name des Containers festgelegt, eine Portweiterleitung durchgeführt und die jeweiligen Volumen mounted. ``` docker run --name SDTest -p 8080:7860 -v C:\Users\Name\Desktop\Docki\ds\extensions:/app/stable-diffusion-webui/extensions -v C:\Users\Name\Desktop\Docki\ds\models:/app/stable-diffusion-webui/models -v C:\Users\Name\Desktop\Docki\ds\outputs:/app/stable-diffusion-webui/outputs -it stablediffown ``` ## Stoppen eines Containers Es gibt 2 Methoden, entweder über die ID, oder über den Container-Namen: Zeige alle laufenden Container an: ``` docker ps ``` Mit ID stoppen: ``` docker stop CONTAINER_ID ``` Mit Container-Namen stoppen: ``` docker stop CONTAINER_NAME ``` ## Erneutes starten eines Containers Hier brauchen die Konfigurationen nicht erneut angegeben werden. Man kann diese aber natürlich, wenn man diese ändern will dennoch angeben. ``` docker start SDTest ``` ## Komplettes entfernen eines Containers ``` docker rm --name=CONTAINER_NAME ```