= 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 <image>`: 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 <image>`: Startet einen Container basierend auf dem angegebenen Image
* `docker exec -it <container> <command>`: Führt einen Befehl in einem laufenden Container aus
* `docker stop <container>`: Stoppt einen laufenden Container
* `docker rm <container>`: Löscht einen gestoppten Container
* `docker rmi <image>`: 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[]






















