= Docker Thomas W. Stütz, credits to Christian Aberger 2.0.0, 2023-04-08: How to use docker in project work @ HTL Leonding college ifndef::imagesdir[:imagesdir: images] //:toc-placement!: // prevents the generation of the doc at this position, so it can be printed afterwards :sourcedir: ../src/main/java :icons: font :sectnums: // Nummerierung der Überschriften / section numbering :toc: left :toclevels: 5 :experimental: true :linkattrs: // so window="_blank" will be executed //Need this blank line after ifdef, don't know why... ifdef::backend-html5[] // https://fontawesome.com/v4.7.0/icons/ icon:file-text-o[link=https://raw.githubusercontent.com/htl-leonding-college/docker-lecture-notes/main/asciidocs/{docname}.adoc] ‏ ‏ ‎ icon:github-square[link=https://github.com/htl-leonding-college/docker-lecture-notes] ‏ ‏ ‎ icon:home[link=https://htl-leonding-college.github.io/docker-lecture-notes/docker.html] endif::backend-html5[] // print the toc here (not at the default position) //toc::[] [[bookmark-document-start]] == Was ist Docker? * Eine Technologie, um eine Applikation und alle ihre Abhängigkeiten in einen einzelnen Container zu packen. * es können mehrere Container auf einem Hostsystem laufen, die sich nicht beeinflussen. So ist es zB möglich mehrere Versionen einer Applikation (zB eine Datenbank) parallel zu betreiben. * Wird eine Applikation in einen Docker-Container gepackt, so ist sichergestellt, dass die Laufzeitumgebung unverändert bleibt, auch wenn der Container auf einem anderen Hostsystem läuft. == Wie funktioniert Docker? //// [plantuml,dockerimage,png] ---- @startuml file dockerfile [ Dockerfile ] artifact image [ docker image ] artifact container [ docker container ] dockerfile -right-> image : docker build image -right-> container : docker run @enduml ---- [plantuml,dockerbuild,png] ---- @startuml cloud "Docker Registry" { artifact "docker\nImage" } artifact image [ docker image ] artifact container [ docker container ] "docker\nImage" -right-> image : docker pull image -right-> container : docker run @enduml ---- //// == Leichtgewichtige Virtualisierung //// .Virtualisierung [plantuml,virt1,png] ---- @startuml rectangle fatvirt [ myApp --- Libraries --- Guest OS --- Hardware Emulation --- VirtualBox / vmware ... --- Host OS --- Hardware ] @enduml ---- .Leichtgewichtige Virtualisierung [plantuml,virt2,png] ---- rectangle docker [ myApp --- Libraries --- Docker --- Host OS --- Hardware ] @enduml ---- //// image:docker-lightweight-virt.png[] * Bsp. für "schwergewichtige" Virtualisierung ** VirtualBox ** vmWare ** ... * Bsp. für leichtgewichtige Virtualisierung ** Docker ** Podman ** ... == Images und Container image::docker-image-container-v2.png[] * *Image*: Immutable Image - die Files könnnen nicht verändert werden. * *Container*: Ein *Prozess*, der auf dem Image basiert. Natürlich möchte der Container Files im Image verändern können. Daher werden die veränderten Files in einem sogenannten *Writable Layer* (hier rosa) gespeichert. Daher ist ein Container nicht nur ein Prozess, sondern beinhaltet auch Files. * *Ports*: Container können Ports freigeben, um mit der Außenwelt zu kommunizieren. * *Volumes*: Container können Volumes mounten, um Daten persistent zu speichern. * *Dockerfile*: Kochrezept zum Erstellen des Images === Übung - Ist Docker installiert? docker version .result ---- % docker version Client: Version: 29.1.3 API version: 1.52 Go version: go1.25.5 Git commit: f52814d Built: Fri Dec 12 14:48:46 2025 OS/Arch: darwin/arm64 Context: desktop-linux Server: Docker Desktop 4.57.0 (215387) Engine: Version: 29.1.3 API version: 1.52 (minimum version 1.44) Go version: go1.25.5 Git commit: fbf3ed2 Built: Fri Dec 12 14:50:40 2025 OS/Arch: linux/arm64 Experimental: false containerd: Version: v2.2.1 GitCommit: dea7da592f5d1d2b7755e3a161be07f43fad8f75 runc: Version: 1.3.4 GitCommit: v1.3.4-0-gd6d73eb8 docker-init: Version: 0.19.0 GitCommit: de40ad0 ---- ---- sudo usermod -a -G docker jenkins ---- == Docker Registries * Woher kommen nun die Images, die für den Betrieb der Container gebraucht werden? ** Entweder bauen wir die Images selbst mit einem Dockerfile (etwas später mehr dazu) ** Oder wir laden die Images aus einer *Docker Registry* herunter * *Docker Registry*: ** a remote repository for storing Docker images ** public or private ** self-hosted or third-party service ** ie Docker Hub, Quay.io image:docker-architecture-v2.png[] === Übung Docker Cowsay ---- docker run --rm ubuntu:24.04 sh -c " apt-get update -y && apt-get install -y cowsay && export PATH=\$PATH:/usr/games && cowsay 'Hello 4xhif'" ---- * -c ... Befehl der in der Shell ausgeführt wird. === Übung: Image alpine ausführen ---- docker run alpine echo Hello 4xhix ---- === Übung: Image alpine interaktiv ---- docker run -it alpine /bin/sh ---- * -it -> interaktives Terminal oder ---- docker run -it ubuntu:24.04 /bin/bash ---- * Mit der Option `--rm` wird der Container nach dem Beenden automatisch gelöscht. === Wichtige Docker-Kommandos: * `docker pull `: Lädt ein Image aus einer Registry herunter * `docker image ls`: Listet alle lokal verfügbaren Images auf (früher `docker images`) * `docker container ls`: Listet alle laufenden Container auf (früher `docker ps`) * `docker container ls -a`: Listet alle Container auf, auch die gestoppten * `docker run `: Startet einen Container basierend auf dem angegebenen Image * `docker exec -it `: Führt einen Befehl in einem laufenden Container aus * `docker stop `: Stoppt einen laufenden Container * `docker rm `: Löscht einen gestoppten Container * `docker rmi `: Löscht ein Image vom lokalen System == Bind Mounts and Volumes image::docker-bindmount-vs-volume.png[] * *Bind Mounts* ein File oder Verzeichnis des Containers wird in einem File oder Verzeichnis am Host zugänglich gemacht ** `docker run -v ${PWD}/directory-on-host:/directory-in-container` * *(Named) Volumes* existieren am Host. Sie werden durch die Docker CLI manipuliert. ** `docker volume create my-volume` ** `docker run -v my-volume:/directory-in-container` * Volumes verfügen über mehr Features wie *Cloud Storage Backends* beim Einsatz in der Cloud (k8s). === Übung: Ubuntu mit einem Volume ---- docker run -it --name syp_ubuntu -v my-opt:/opt ubuntu:24.04 /bin/bash ---- .ansehen mit ---- docker volume ls ---- === Übung: Ubuntu mit einem bind mount ---- docker run -it --name syp_ubuntu -v ${PWD}/my_opt:/opt ubuntu:24.04 /bin/bash ---- .ansehen mit ---- ls -lah ./my_opt ---- === Übung: Ubuntu mit einem Volume ---- # ist nicht notwendig, wird automatisch erstellt docker volume create my_volume docker run -it --name syp_ubuntu -v my_volume:/opt ubuntu:24.04 /bin/bash ---- * erstelle ein file im opt-folder: `echo 123 > my-file.txt` * beende container * lösche container * erstelle und starte einen neuen Container -> das File befindet sich immer noch im Volume == Ports * In einem Container laufen meist Dienste, wie zB Webserver oder Datenbanken. * Diese Dienste müssen über das Netzwerk erreichbar sein. * Container sind per default von außen nicht erreichbar. * Um einen Dienst im Container erreichbar zu machen, müssen Ports freigegeben werden. === Übung: nginx - Step 1 .Starting nginx ---- docker run --rm -p 8081:80 --name nginx nginx ---- image:docker-port-mapping.png[] === Übung: nginx - Step 2 .Terminal 1: Starting nginx ---- docker run --rm -p 8081:80 --name nginx nginx ---- .Terminal 2: Open a terminal in the docker container ---- docker exec -it nginx /bin/sh ---- === Übung: nginx - Step 3 .Terminal 1: Start nginx with a volume in the current folder ---- docker run --rm -v ${PWD}/data:/usr/share/nginx/html -p 8081:80 --name nginx nginx ---- image:docker-starten-nginx.png[] .Image + Container (w/ port + volume) image:docker-nginx.png[] === Übung: PostgreSQL ---- docker run -it \ --rm=true \ --name postgres \ -v ${PWD}/pgdata:/var/lib/postgresql/data \ -e POSTGRES_USER=app \ -e POSTGRES_PASSWORD=app \ -e POSTGRES_DB=db \ -p 5432:5432 postgres:18.1 ---- === Übung: Minecraft .https://hub.docker.com/r/itzg/minecraft-server[Minecraft Server] [source,shell script] ---- docker pull itzg/minecraft-server docker run -d -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server ---- * https://hub.docker.com/r/itzg/minecraft-server[Documentation on Docker Hub^] * https://github.com/itzg/docker-minecraft-server/blob/master/README.md[Documentation on github^] == Unterschied zum Arbeiten ohne Docker * Ohne Docker werden auf einer Maschine mehrere Softwareprodukte installiert * Bei Verwendung von Docker wird für jedes Softwareprodukt ein eigener Docker-Container erstellt == Docker Networks * Konfiguriert die Verbindung zwischen Container und zum Internet * Container können ports freigeben und so im Internet verfügbar machen * Man verwendet die *Docker CLI* * Network Drivers ** *Bridge*: Virtuelles Netzwerk, um mehrere Container miteinander zu verbinden ** *Host*: Entfernt die Netzwerk-Isolation zwischen Host und Containern. Die Container benutzen das Netzwerk des Hosts direkt ** *Overlay*: Verbindet Container die auf unterschiedlichen Docker-Hosts laufen ** *Macvlan*: Weist eine MAC-Adresse einem Container zu. Für low-level Netzwerkanforderungen ** *None*: Deaktiviert das Netzwerk zwischen den Containern image:docker-network.png[]