HelperSheets/docker/Docker.md

229 lines
8.2 KiB
Markdown
Raw Permalink Normal View History

2024-08-26 18:09:02 +02:00
# 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):<br>
[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.<br>
Relative Pfade:<br>
```./verzeichnis/auf/...```<br>
Absolute Pfade:<br>
```/verzeichnis/auf/...```<br>
⚠️ Die Ordner müssen auf dem Host System existieren. ⚠️ <br>
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:* <br>
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
```