Docker: Unterschied zwischen den Versionen

Aus Foxwiki
Wechseln zu:Navigation, Suche
Keine Bearbeitungszusammenfassung
 
(181 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
== Einführung ==
<noinclude>
; Container sind eine schlanke Virtualisierungslösung
----
Dabei laufen die Prozesse direkt im Kernel des Host-Betriebssystems, aber abgeschottet von den anderen Prozessen durch Linux-Techniken wie
{{Navigation|Docker|Dockersieren|Aktualisieren}}
* cgroups
----
* namespaces
'''Docker''' - [[Containervirtualisierung|Container-Virtualisierung]] zur Isolierung von Anwendungen
* unter Windows kommt dafür der WSL2 zum Einsatz
<noinclude>
* unter macOS wird eine kleine Virtualisierung genutzt


Container sind nützlich, wenn an mehreren Stellen eine identische Arbeitsumgebung benötigt wird
== Docker ==
* Man kann dabei entweder die Images (fertige Dateien) oder die Dockerfiles (Anweisungen zum Erzeugen eines Images) im Projekt verteilen
; Schlanke Form der Virtualisierungen
* Tatsächlich ist es nicht unüblich, ein Dockerfile in das Projekt-Repo mit einzuchecken
[[File:dockerDevelopFaster.png|mini|500px]]
* Prozesse laufen auf dem Kernel des Host-Betriebssystems
* Abschottung durch
** [[cgroups]]
** [[namespaces]]
** …


; Kein Sicherheitsgewinn
=== Linzenz ===
Durch Container hat man allerdings im Gegensatz zu herkömmlichen VMs keinen Sicherheitsgewinn, da die im Container laufende Software ja direkt auf dem Host-Betriebssystem ausgeführt wird
[[Docker]] ist [[freie Software]]


; Fertige Images
=== Realisierung von Containern ===
Es gibt auf DockerHub fertige Images, die man sich ziehen und starten kann
; Linux-Techniken
* Ein solches gestartetes Image nennt sich dann Container und enthält beispielsweise Dateien, die in den Container gemountet oder kopiert werden
[[Datei:Docker-linux-interfaces.svg|mini|400px|Schnittstellen, um auf Virtualisierungsfunktionen des Linux-Kernels zuzugreifen.]]
* Man kann auch eigene Images bauen, indem man eine entsprechende Konfiguration (Dockerfile) schreibt
* [[cgroups]]
* Jeder Befehl bei der Erstellung eines Images erzeugt einen neuen Layer, die sich dadurch mehrere Images teilen können
* [[Namespaces]]
* Anfänglich [[LXC]]-Schnittstelle des [[Linux (Kernel)|Linux-Kernels]]


In der Konfiguration einer Gitlab-CI-Pipeline kann man mit <code>image</code> ein Docker-Image angeben, welches dann in der Pipeline genutzt wird
; libcontainer
Mittlerweile eine eigene [[Programmierschnittstelle]] namens '''[[libcontainer]]'''


VSCode kann über das Remote-Plugin sich (u.a.) mit Containern verbinden und dann im Container arbeiten (editieren, compilieren, debuggen, testen, ...)
; Speicher-Frontend
Als Speicher-[[Frontend und Backend|Backend]] verwendet Docker das [[Overlay-Dateisystem]] [[aufs]]
** Seit Version 0.8 wird [[btrfs]] unterstützt
<br clear=all>


In dieser kurzen Einheit kann ich Ihnen nur einen ersten Einstieg in das Thema geben
=== Begriffe ===
* Wir haben uns beispielsweise nicht Docker Compose oder Kubernetes angeschaut, und auch die Themen Netzwerk (zwischen Containern oder zwischen Containern und anderen Rechnern) und Volumnes habe ich außen vor gelassen
{| class="table table-striped table-hover col1bold col1nowrap"
* Dennoch kommt man in der Praxis bereits mit den hier vermittelten Basiskenntnissen erstaunlich weit
|-
! Begriff !! Beschreibung
|-
| [[Docker/Volume|Volume]] || Volumes ermöglichen es, dass Daten erhalten bleiben, auch wenn ein Docker-Container gelöscht wird. Volumes sind auch eine praktische Möglichkeit, Daten zwischen dem Host und dem Container auszutauschen.
|-
| [[Docker/Image|Image]] || Ein Docker-Image ist eine schreibgeschützte Vorlage, die von der Docker-Engine benutzt wird, um einen Container zu erzeugen.
[[Image-Datei|Speicherabbild]] eines Containers
* Das Image selbst besteht aus mehreren Layern, die schreibgeschützt sind und somit nicht verändert werden können
* Ein Image ist portabel, kann in [[Repository|Repositories]] gespeichert und mit anderen Nutzern geteilt werden
* Aus einem Image können immer mehrere Container gestartet werden
|-
| [[Docker/Container|Container]] || Docker-Container sind isolierte Ausführungseinheiten für Anwendungen und ihre Abhängigkeiten
Aktive Instanz eines Images
* Der Container wird also gerade ausgeführt und ist beschäftigt
* Sobald der Container kein Programm ausführt oder mit seinem Auftrag fertig ist, wird der Container automatisch beendet
|-
| [[Docker/Layer|Layer]] || Teil eines Images und enthält einen Befehl oder eine Datei, die dem Image hinzugefügt wurde
* Anhand der Layer kann die ganze Historie des Images nachvollzogen werden
|-
| [[Docker/Dockerfile|Dockerfile]] || Beschreibung zur Erstellung eines Docker-Container
* [[Textdatei]], die mit verschiedenen Befehlen ein Image beschreibt
* werden bei der Ausführung abgearbeitet und für jeden Befehl wird ein einzelner Layer angelegt
|-
| [[Docker/Repository|Repository]] || Satz gleichnamiger Images mit verschiedenen Tags, zumeist Versionen
|-
| [[Docker/Registry|Registry]] || Verwaltung von Repositories (''Docker Hub'', ''Artifactory'', ...)
|}


Videos (YouTube)
=== Bibliotheken ===
* VL Einführung in Docker
{| class="table table-striped table-hover col1bold col1nowrap"
* Demo Container in der Konsole
|-
* Demo GitLab CI/CD und Docker
! Begriff !! Beschreibung
* Demo GitHub Actions und Docker
|-
* Demo VSCode und Docker
| [[Docker/libcontainer|libcontainer]] || Schnittstelle zu den Grundfunktionen von Docker
|-
| [[Docker/libswarm|libswarm]] || Schnittstelle, um Docker-Container zu steuern
|-
| [[Docker/libchan|libchan]] || Einfache („light weighted“) Kommunikation zwischen Prozessteilen und Prozessen
|}


Videos (HSBI-Medienportal)
== Aufbau und Funktionen ==
* VL Einführung in Docker
; „Build, Ship and Run Any App, Anywhere“
[[Image:01_csm_virtuelle-maschinen-vs-docker-vergleich_2b58cdd628.webp|mini|400px|alt="Bild: Virtuelle Maschinen und Docker-Container im Vergleich"| Während jede virtuelle Maschine ein eigenes Betriebssystem startet, teilen sich Docker-Container den Kernel des Host-Systems ]]


Lernziele
Unter diesem Motto bewirbt die quelloffene Container-Plattform Docker eine flexible, ressourcensparende Alternative zur Emulation von Hardware-Komponenten auf Basis virtueller Maschinen (VMs)
* (K2) Unterschied zwischen Containern und VMs
* Während die '''klassische Hardware-Virtualisierung''' darauf beruht, mehrere Gastsysteme auf einem gemeinsamen Host-System zu starten, werden Anwendungen bei Docker mithilfe von '''Containern''' als isolierte Prozesse auf ein und demselben System ausgeführt
* (K2) Einsatzgebiete für Container
* Man spricht bei der containerbasierten Server-Virtualisierung daher auch von einer '''Operating-System-Level-Virtualisierung'''
* (K2) Container laufen als abgeschottete Prozesse auf dem Host - kein Sandbox-Effekt
* (K3) Container von DockerHub ziehen
* (K3) Container starten
* (K3) Eigene Container definieren und bauen
* (K3) Einsatz von Containern in GitLab CI/CD und GitHub Actions
* (K3) Einsatz von VSCode und Containern


=== Motivation ===
Der Vorteil containerbasierter Virtualisierung liegt somit darin, dass sich Anwendungen mit unterschiedlichen Anforderungen isoliert voneinander ausführen lassen, ohne dass dafür der Overhead eines separaten Gastsystems in Kauf genommen werden muss
; <nowiki>Motivation CI/CD: WFM (''Works For Me'')</nowiki>
* Zusätzlich können Anwendungen mit Container '''plattformübergreifend und in unterschiedlichen Infrastrukturen''' eingesetzt werden, ohne dass diese an die Hard- oder Software-Konfigurationen des Hostsystems angepasst werden müssen
Auf dem CI-Server muss man eine Arbeitsumgebung konfigurieren und bereitstellen, für Java-basierte Projekte muss beispielsweise ein JDK existieren und man benötigt Tools wie Maven oder Gradle, um die Buildskripte auszuführen
* Je nach Projekt braucht man dann noch weitere Tools und Bibliotheken
* Diese Konfigurationen sind unabhängig vom CI-Server und werden üblicherweise nicht direkt installiert, sondern über eine Virtualisierung bereitgestellt


Selbst wenn man keine CI-Pipelines einsetzt, hat man in Projekten mit mehreren beteiligten Personen häufig das Problem "''WFM''" ("works for me")
Docker ist das bekannteste Software-Projekt, das Anwendern und Anwenderinnen eine '''auf Containern basierende Virtualisierungstechnologie''' zur Verfügung stellt
* Jeder Entwickler hat sich auf ihrem Rechner eine Entwicklungsumgebung aufgesetzt und nutzt in der Regel seine bevorzugte IDE oder sogar unterschiedliche JDK-Versionen
* Die quelloffene Plattform setzt dabei auf drei grundlegende Komponenten: Um Container auszuführen, brauchen Anwender lediglich die '''[[Docker/Engine|Docker-Engine]]''' sowie spezielle '''[[Docker/Image|Docker-Images]]''', die sich über das '''[[Docker/Hub|Docker-Hub]]''' beziehen oder selbst erstellen lassen
* Dadurch kann es schnell passieren, dass Probleme oder Fehler auftreten, die sich nicht von allen Beteiligten immer nachvollziehen lassen
* Hier wäre eine einheitliche Entwicklungsumgebung sinnvoll, die in einer "schlanken" Virtualisierung bereitgestellt wird


Als Entwickler kann man zeitgleich in verschiedenen Projekten beteiligt sein, die unterschiedliche Anforderungen an die Entwicklungstools mit sich bringen
=== Motivation ===
* Es könnte beispielsweise passieren, dass man zeitgleich drei bestimmte Python-Versionen benötigt
; Vereinfachte Bereitstellung von Anwendungen
* In den meisten Fällen schafft man es (mit ein wenig Aufwand), diese Tools nebeneinander zu installieren
* Container, die alle nötigen Pakete enthalten leicht als Dateien transportieren und installieren lassen
* Oft ist das in der Praxis aber schwierig und fehleranfällig
* Geringerer Overhead durch geteilten Host-Kernel
* Schnelle Start- und Stopzeiten
* Hohe Dichte isolierter Instanzen pro Host
* Prozess- und Abhängigkeitsisolation (Namespaces, cgroups)
* Reproduzierbare Laufzeitumgebungen durch unveränderliche Images
* Portabilität über unterschiedliche Hosts und Plattformen
* Feingranulares Ressourcen- und Zugriffsmanagement
* Vereinfachtes Lebenszyklus-Management


In diesen Fällen kann eine Virtualisierung helfen
; Container gewährleisten
Trennung und Verwaltung der auf einem Rechner genutzten Ressourcen
* Code
* Laufzeitmodul
* Systemwerkzeuge
* Systembibliotheken
* alles was auf einem Rechner installiert werden kann


=== Container vs.&nbsp;VM ===
=== Container ===
Wenn man über Virtualisierung auf dem Desktop spricht, kann man grob zwei Varianten unterscheiden
; Sandbox-Prozess
* In beiden Fällen ist die Basis die Hardware (Laptop, Desktop-Rechner) und das darauf laufende (Host-) Betriebssystem (Linux, FreeBSD, macOS, Windows, ...)
Ein Container ist ein Sandbox-Prozess, der auf einem Host-Computer ausgeführt wird und von allen anderen auf diesem Host-Computer ausgeführten Prozessen isoliert ist
* Darauf läuft dann wiederum die Virtualisierung
* Diese Isolierung nutzt Kernel-Namespaces und cgroups, Funktionen, die es in Linux schon seit langem gibt
* Docker macht diese Funktionen zugänglich und einfach zu verwenden
* Ein ist Container eine lauffähige Instanz eines Images


Im rechten Bild wird eine herkömmliche Virtualisierung mit virtuellen Maschinen (''VM'') dargestellt
; Container werden über die Docker-API oder die Befehlszeilenschnittstelle
* Dabei wird in der VM ein komplettes Betriebssystem (das "Gast-Betriebssystem") installiert und darin läuft dann die gewünschte Anwendung
* erstellt
* Die Virtualisierung (VirtualBox, VMware, ...) läuft dabei als Anwendung auf dem Host-Betriebssystem und stellt dem Gast-Betriebssystem in der VM einen Rechner mit CPU, RAM,
* gestartet
* zur Verfügung und übersetzt die Systemaufrufe in der VM in die entsprechenden Aufrufe im Host-Betriebssystem
* angehalten
* Dies benötigt in der Regel entsprechende Ressourcen: Durch das komplette Betriebssystem in der VM ist eine VM (die als Datei im Filesystem des Host-Betriebssystems liegt) oft mehrere 10GB groß
* verschoben
* Für die Übersetzung werden zusätzlich Hardwareressourcen benötigt, d.h
* gelöscht
* hier gehen CPU-Zyklen und RAM "verloren"
* Das Starten einer VM dauert entsprechend lange, da hier ein komplettes Betriebssystem hochgefahren werden muss
* Dafür sind die Prozesse in einer VM relativ stark vom Host-Betriebssystem abgekapselt, so dass man hier von einer "Sandbox" sprechen kann: Viren o.ä
* können nicht so leicht aus einer VM "ausbrechen" und auf das Host-Betriebssystem zugreifen (quasi nur über Lücken im Gast-Betriebssystem kombiniert mit Lücken in der Virtualisierungssoftware)


Im linken Bild ist eine schlanke Virtualisierung auf Containerbasis dargestellt
; Er kann auf lokalen oder virtuellen Maschinen ausgeführt oder in der Cloud bereitgestellt werden
* Die Anwendungen laufen direkt als Prozesse im Host-Betriebssystem, ein Gast-Betriebssystem ist nicht notwendig
* Er ist portabel (und kann auf jedem Betriebssystem ausgeführt werden)
* Durch den geschickten Einsatz von <code>namespaces</code> und <code>cgroups</code> und anderen in Linux und FreeBSD verfügbaren Techniken werden die Prozesse abgeschottet, d.h
* Er ist von anderen Containern isoliert und führt seine eigene Software, Binärdateien, Konfigurationen usw
* der im Container laufende Prozess "sieht" die anderen Prozesse des Hosts nicht
* Die Erstellung und Steuerung der Container übernimmt hier beispielsweise Docker
* Die Container sind dabei auch wieder Dateien im Host-Filesystem
* Dadurch benötigen Container wesentlich weniger Platz als herkömmliche VMs, der Start einer Anwendung geht deutlich schneller und die Hardwareressourcen (CPU, RAM, ...) werden effizient genutzt
* Nachteilig ist, dass hier in der Regel ein Linux-Host benötigt wird (für Windows wird mittlerweile der Linux-Layer (''WSL'') genutzt; für macOS wurde bisher eine Linux-VM im Hintergrund hochgefahren, mittlerweile wird aber eine eigene schlanke Virtualisierung eingesetzt)
* Außerdem steht im Container üblicherweise kein graphisches Benutzerinterface zur Verfügung
* Da die Prozesse direkt im Host-Betriebssystem laufen, stellen Container keine Sicherheitsschicht ("Sandboxen") dar!


In allen Fällen muss die Hardwarearchitektur beachtet werden: Auf einer Intel-Maschine können normalerweise keine VMs/Container basierend auf ARM-Architektur ausgeführt werden und umgekehrt
; Erweiterte Form von chroot
* Das Dateisystem wird aus einem Image bereitgestellt
* Allerdings bietet der Container eine zusätzliche Isolation, die mit chroot nicht möglich ist


== Images selbst definieren ==
; Siehe auch
<code>FROM debian:stable-slim
* [[Docker/Container|Container]]


ARG USERNAME=pandoc
=== Bereitstellung ===
ARG USER_UID=1000
; Image oder Dockerfile
ARG USER_GID=1000
* Fertige Images
* Dockerfiles
** Anweisungen zum Erzeugen eines Images (Dockerfiles) im Projekt verteilen
** Dockerfiles können gut in Projekt-Repositoies bereitgestellt werden


RUN apt-get update && apt-get install -y --no-install-recommends \
=== Fertige Images ===
apt-utils bash wget make graphviz biber \
DockerHub bietet fertige Images
texlive-base texlive-plain-generic texlive-latex-base \
* Ein solches gestartetes Image nennt sich dann Container und enthält beispielsweise Dateien, die in den Container gemountet oder kopiert werden
#
* Man kann auch eigene Images bauen, indem man eine entsprechende Konfiguration (Dockerfile) schreibt
&& groupadd --gid $USER_GID $USERNAME \
* Jeder Befehl bei der Erstellung eines Images erzeugt einen neuen Layer, die sich dadurch mehrere Images teilen können
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
#
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*


WORKDIR /pandoc
In der Konfiguration einer Gitlab-CI-Pipeline kann man mit <code>image</code> ein Docker-Image angeben, welches dann in der Pipeline genutzt wird
USER $USERNAME</code>
<code>docker build -t <NAME> -f <DOCKERFILE> .</code>


<code>FROM</code> gibt die Basis an, d.&nbsp;h.&nbsp;hier ein Image von Debian in der Variante <code>stable-slim</code>, d.&nbsp;h.&nbsp;das ist der Basis-Layer für das zu bauende Docker-Image
=== Docker Images ===
Ähnlich wie virtuelle Maschinen basieren Docker-Container auf [[Docker/Image|Images]]


Über <code>ARG</code> werden hier Variablen gesetzt
; Schreibgeschützte Vorlage
Dieses isolierte Dateisystem wird von einem Image bereitgestellt, und das Image muss alles enthalten, was zur Ausführung einer Anwendung erforderlich ist - alle Abhängigkeiten, Konfigurationen, Skripte, Binärdateien und so weiter.


<code>RUN</code> ist der Befehl, der im Image (hier Debian) ausgeführt wird und einen neuen Layer hinzufügt
; Portables Abbild eines Containers
* In diesen Layer werden alle Dateien eingefügt, die bei der Ausführung des Befehls erzeugt oder angelegt werden
Als wird ein Docker-Image in Form einer Textdatei beschrieben – man spricht von einem [[Docker/Dockerfile|Dockerfile]]
* Hier im Beispiel wird das Debian-Tool <code>apt-get</code> gestartet und weitere Debian-Pakete installiert
* Soll ein Container auf einem System gestartet werden, wird zunächst ein Paket mit dem jeweiligen Image geladen – sofern dieses nicht lokal vorliegt
* Das geladene Image stellt das für die Laufzeit benötigte '''Dateisystem inklusive aller Parameter''' bereit
* Ein Container kann als laufender Prozess eines Images betrachtet werden


Da jeder <code>RUN</code>-Befehl einen neuen Layer anlegt, werden die restlichen Konfigurationen ebenfalls in diesem Lauf durchgeführt
; Siehe auch
* Insbesondere wird ein nicht-Root-User angelegt, der von der UID und GID dem Default-User in Linux entspricht
* [[Docker/Images selbst definieren|Images selbst definieren]]
* Die gemounteten Dateien haben die selben Rechte wie auf dem Host, und durch die Übereinstimmung von UID/GID sind die Dateien problemlos zugreifbar und man muss nicht mit dem Root-User arbeiten (dies wird aus offensichtlichen Gründen als Anti-Pattern angesehen)
* Bevor der <code>RUN</code>-Lauf abgeschlossen wird, werden alle temporären und später nicht benötigten Dateien von <code>apt-get</code> entfernt, damit diese nicht Bestandteil des Layers werden


Mit <code>WORKDIR</code> und <code>USER</code> wird das Arbeitsverzeichnis gesetzt und auf den angegebenen User umgeschaltet
== Docker-Engine ==
* Damit muss der User nicht mehr beim Aufruf von außen gesetzt werden
Mit [[Docker/Befehle|Docker-Befehlen]] können Anwenderinnen und Anwender Software-Container direkt aus dem Terminal starten, stoppen und verwalten
* Die Ansprache des Daemon erfolgt über das Kommando dockerund Anweisungen wie build (erstelle), pull (lade herunter) oder run (starte)
* Client und Server können sich dabei auf dem gleichen System befinden
* Alternativ steht Anwendern die Möglichkeit offen, einen Docker-Daemon auf einem anderen System anzusprechen
* Je nachdem, welche Art von Verbindung aufgebaut werden soll, erfolgt die Kommunikation zwischen Client und Server über die REST-API, über UNIX-Sockets oder eine Netzwerkschnittstelle


Über <code>docker build -t <NAME> -f <DOCKERFILE> .</code> wird aus dem angegebenen Dockerfile und dem Inhalt des aktuellen Ordners ("<code>.</code>") ein neues Image erzeugt und mit dem angegebenen Namen benannt
=== Komponenten ===
Zusammenspiel der Docker-Komponenten
[[Image:03_csm_schematische-darstellung-docker-architektur_0cbba145c8.webp|mini|400px|alt="Bild: Schematische Darstellung der Docker-Architektur"|Die Docker-Architektur basiert auf einem Zusammenspiel aus Client (Terminal), Server (Docker-Daemon) und Registry (Docker-Hub)]]


'''Hinweis zum Umgang mit Containern und Updates''': Bei der Erstellung eines Images sind bestimmte Softwareversionen Teil des Images geworden
; Beispiel
* Man kann prinzipiell in einem Container die Software aktualisieren, aber dies geht in dem Moment wieder verloren, wo der Container beendet und gelöscht wird
docker build
* Außerdem widerspricht dies dem Gedanken, dass mehrere Personen mit dem selben Image/Container arbeiten und damit auch die selben Versionsstände haben
* In der Praxis löscht man deshalb das alte Image einfach und erstellt ein neues, welches dann die aktualisierte Software enthält


== CI-Pipeline (GitLab) ==
  docker pull
  <code>default:
image: openjdk:17


  job1:
  docker run
stage: build
script:
- java -version
- javac Hello.java
- java Hello
- ls -lags</code>
In den Gitlab-CI-Pipelines (analog wie in den GitHub-Actions) kann man Docker-Container für die Ausführung der Pipeline nutzen


Mit <code>image: openjdk:17</code> wird das Docker-Image <code>openjdk:17</code> vom DockerHub geladen und durch den Runner für die Stages als Container ausgeführt
; docker build
* Die Aktionen im <code>script</code>-Teil, wie beispielsweise <code>javac Hello.java</code> werden vom Runner an die Standard-Eingabe der Shell des Containers gesendet
Das Kommando docker build weist den Docker-Daemon an, ein Image zu erstellen (gepunktete Linie)
* Im Prinzip entspricht das dem Aufruf auf dem lokalen Rechner: <code>docker run openjdk:17 javac Hello.java</code>
* Dazu muss ein entsprechendes [[Dockerfile]] vorliegen


== CI-Pipeline (GitHub) ==
Soll das Image nicht selbst erstellt, sondern aus einem Repository im Docker-Hub geladen werden, kommt das Kommando docker pull zum Einsatz (gestrichelte Linie)
<code>name: demo
* Wird der Docker-Daemon via docker run angewiesen, einen Container zu starten, prüft das Hintergrundprogramm zunächst, ob das entsprechende Container-Image lokal vorliegt
on:
* Ist dies der Fall, wird der Container ausgeführt (durchgezogene Linie)
push:
* Kann der Daemon das Image nicht finden, leitet dieser automatisch ein Pulling aus dem Repository ein
branches: [master]
workflow_dispatch:


jobs:
=== Betriebssysteme ===
job1:
; Virtualisierung mit [[Linux]]
runs-on: ubuntu-latest
Docker auf die Virtualisierung mit [[Linux]] ausgerichtet
container: docker://openjdk:17
* Docker-Technologie benötigt einen [[Linux-Kernel]]
steps:
- uses: actions/checkout@v4
- run: java -version
- run: javac Hello.java
- run: java Hello
- run: ls -lags</code>
<nowiki>https://stackoverflow.com/questions/71283311/run-github-workflow-on-docker-image-with-a-dockerfile</nowiki> <nowiki>https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container</nowiki>


In den GitHub-Actions kann man Docker-Container für die Ausführung der Pipeline nutzen
== Container und Virtuelle Maschinen ==
; Varianten
* Hardware
* Betriebssystem
** Linux, FreeBSD, macOS, Windows, …
* Virtualisierung


Mit <code>docker://openjdk:17</code> wird das Docker-Image <code>openjdk:17</code> vom DockerHub geladen und auf dem Ubuntu-Runner als Container ausgeführt
=== Herkömmliche Virtualisierung ===
* Die Aktionen im <code>steps</code>-Teil, wie beispielsweise <code>javac Hello.java</code> werden vom Runner an die Standard-Eingabe der Shell des Containers gesendet
<s>Im rechten Bild</s> wird eine herkömmliche Virtualisierung mit virtuellen Maschinen (''VM'') dargestellt
* Im Prinzip entspricht das dem Aufruf auf dem lokalen Rechner: <code>docker run openjdk:17 javac Hello.java</code>
* Dabei wird in der VM ein komplettes Betriebssystem (das "Gast-Betriebssystem") installiert und darin läuft dann die gewünschte Anwendung
* Die Virtualisierung (VirtualBox, VMware, ...) läuft dabei als Anwendung auf dem Host-Betriebssystem und stellt dem Gast-Betriebssystem in der VM einen Rechner mit CPU, RAM, zur Verfügung und übersetzt die Systemaufrufe in der VM in die entsprechenden Aufrufe im Host-Betriebssystem
* Dies benötigt in der Regel entsprechende Ressourcen: Durch das komplette Betriebssystem in der VM ist eine VM (die als Datei im Filesystem des Host-Betriebssystems liegt) oft mehrere 10GB groß
* Für die Übersetzung werden zusätzlich Hardwareressourcen benötigt, d.&nbsp;h.&nbsp;hier gehen CPU-Zyklen und RAM "verloren"
* Das Starten einer VM dauert entsprechend lange, da hier ein komplettes Betriebssystem hochgefahren werden muss
* Dafür sind die Prozesse in einer VM relativ stark vom Host-Betriebssystem abgekapselt, so dass man hier von einer "Sandbox" sprechen kann: Viren o.ä
* können nicht so leicht aus einer VM "ausbrechen" und auf das Host-Betriebssystem zugreifen (quasi nur über Lücken im Gast-Betriebssystem kombiniert mit Lücken in der Virtualisierungssoftware)


== VSCode und das Plugin "Remote - Containers" ==
=== Container ===
; Virtualisierung auf Containerbasis
<s>Im linken Bild</s> ist eine schlanke Virtualisierung auf Containerbasis dargestellt
* Die Anwendungen laufen direkt als Prozesse im Host-Betriebssystem, ein Gast-Betriebssystem ist nicht notwendig
* Durch den geschickten Einsatz von <code>namespaces</code> und <code>cgroups</code> und anderen in Linux und FreeBSD verfügbaren Techniken werden die Prozesse abgeschottet, d.&nbsp;h.&nbsp;der im Container laufende Prozess "sieht" die anderen Prozesse des Hosts nicht
* Die Erstellung und Steuerung der Container übernimmt hier beispielsweise Docker
* Die Container sind dabei auch wieder Dateien im Host-Filesystem
* Dadurch benötigen Container wesentlich weniger Platz als herkömmliche VMs, der Start einer Anwendung geht deutlich schneller und die Hardwareressourcen (CPU, RAM, ...) werden effizient genutzt
* Nachteilig ist, dass hier in der Regel ein Linux-Host benötigt wird (für Windows wird mittlerweile der Linux-Layer (''WSL'') genutzt; für macOS wurde bisher eine Linux-VM im Hintergrund hochgefahren, mittlerweile wird aber eine eigene schlanke Virtualisierung eingesetzt)
* Außerdem steht im Container üblicherweise kein graphisches Benutzerinterface zur Verfügung
* Da die Prozesse direkt im Host-Betriebssystem laufen, stellen Container keine Sicherheitsschicht ("Sandboxen") dar!


# VSCode (Host): Plugin "Remote - Containers" installieren
In allen Fällen muss die Hardwarearchitektur beachtet werden: Auf einer Intel-Maschine können normalerweise keine VMs/Container basierend auf ARM-Architektur ausgeführt werden und umgekehrt
# Docker (Host): Container starten mit Workspace gemountet
# VSCode (Host): Attach to Container => neues Fenster (Container)
# VSCode (Container): Plugin "Java Extension Pack" installieren
# VSCode (Container): Dateien editieren, kompilieren, debuggen,
 
Mit Visual Studio Code (VSC) kann man über SSH oder in einem Container arbeiten
* Dazu installiert man sich VSC lokal auf dem Host und installiert dort das Plugin "Remote - Containers"
* VSC kann darüber vordefinierte Docker-Images herunterladen und darin arbeiten oder man kann alternativ einen Container selbst starten und diesen mit VSC verbinden ("attachen")
 
Beim Verbinden öffnet VSC ein neues Fenster, welches mit dem Container verbunden ist
* Nun kann man in diesem neuen Fenster ganz normal arbeiten, allerdings werden alle Dinge in dem Container erledigt
* Man öffnet also Dateien in diesem Container, editiert sie im Container, übersetzt und testet im Container und nutzt dabei die im Container installierten Tools
* Sogar die entsprechenden VSC-Plugins kann man im Container installieren


Damit benötigt man auf einem Host eigentlich nur noch VSC und Docker, aber keine Java-Tools o.ä
<noinclude>
* und kann diese über einen im Projekt definierten Container (über ein mit versioniertes Dockerfile) nutzen
== Anhang ==
 
=== Siehe auch ===
''Anmerkung'': IntelliJ kann remote nur debuggen, d.&nbsp;h.&nbsp;das Editieren, Übersetzen, Testen läuft lokal auf dem Host (und benötigt dort den entsprechenden Tool-Stack)
; Kategorien
* Für das Debuggen kann Idea das übersetzte Projekt auf ein Remote (SSH, Docker) schieben und dort debuggen
<div style="column-count:2">
 
<categorytree hideroot=on mode="category">Docker</categorytree>
Noch einen Schritt weiter geht das Projekt code-server: Dieses stellt u.&nbsp;a.&nbsp;ein Docker-Image codercom/code-server bereit, welches einen Webserver startet und über diesen kann man ein im Container laufendes (angepasstes) VSC erreichen
</div>
* Man braucht also nur noch Docker und das Image und kann dann über den Webbrowser programmieren
; Unterseiten
* Der Projektordner wird dabei in den Container gemountet, so dass die Dateien entsprechend zur Verfügung stehen:
{{Special:PrefixIndex/Docker/}}
<code>docker run -it --name code-server -p 127.0.0.1:8080:8080 -v "$HOME/.config:/home/coder/.config" -v "$PWD:/home/coder/project" codercom/code-server:latest</code>
Auf diesem Konzept setzt auch der kommerzielle Service GitHub Codespaces von GitHub auf
 
== Link-Sammlung ==
* Wikipedia: Docker
* Wikipedia: Virtuelle Maschinen
* Docker: Überblick, Container
* Docker: HowTo
* DockerHub: Suche nach fertigen Images
* Docker und Java
* Dockerfiles: Best Practices
* Gitlab, Docker
* VSCode: Entwickeln in Docker-Containern
* [DockerInAction] und [DockerInPractice]
 
== Wrap-Up ==
* Schlanke Virtualisierung mit Containern (kein eigenes OS)
* ''Kein'' Sandbox-Effekt
* Begriffe: Docker-File vs.&nbsp;Image vs.&nbsp; Container
* Ziehen von vordefinierten Images
* Definition eines eigenen Images
* Arbeiten mit Containern: lokal, CI/CD, VSCode
 
Quizzes
* Quiz Docker (ILIAS)
 
Quellen
* [DockerInAction] '''Docker in Action''' Nickoloff, D., Manning Publications, 2019. ISBN 978-1-6172-9476-1
* [DockerInPractice] '''Docker in Practice''' Miell, I. und Sayers, A. H., Manning Publications, 2019. ISBN 978-1-6172-9480-8
* [Inden2013] '''Der Weg zum Java-Profi''' Inden, M., dpunkt.verlag, 2013. ISBN 978-3-8649-1245-0


=== Links ===
==== Weblinks ====
# https://docs.docker.com
# https://hub.docker.com/search
# https://de.wikipedia.org/wiki/Docker_(Software)
# https://www.hsbi.de/elearning/data/FH-Bielefeld/lm_data/lm_1359639/building/docker.html
# https://www.hsbi.de/elearning/data/FH-Bielefeld/lm_data/lm_1359639/building/docker.html
# [https://www.docker.com/ Offizielle Website]
# [http://www.admin-magazin.de/Das-Heft/2014/02/Renaissance-der-Container-Virtualisierung-mit-Docker Renaissance der Container-Virtualisierung mit Docker]
# [https://www.informatik-aktuell.de/entwicklung/methoden/containerplattform-lego-fuer-devops.html Einführung und Praxisbeispiele / Übersicht Docker und Container-Virtualisierung]


[[Kategorie:Docker]]
[[Kategorie:Docker]]
</noinclude>

Aktuelle Version vom 1. Oktober 2026, 12:05 Uhr



Docker - Container-Virtualisierung zur Isolierung von Anwendungen


Docker

Schlanke Form der Virtualisierungen
  • Prozesse laufen auf dem Kernel des Host-Betriebssystems
  • Abschottung durch

Linzenz

Docker ist freie Software

Realisierung von Containern

Linux-Techniken
Schnittstellen, um auf Virtualisierungsfunktionen des Linux-Kernels zuzugreifen.
libcontainer

Mittlerweile eine eigene Programmierschnittstelle namens libcontainer

Speicher-Frontend

Als Speicher-Backend verwendet Docker das Overlay-Dateisystem aufs

    • Seit Version 0.8 wird btrfs unterstützt


Begriffe

Begriff Beschreibung
Volume Volumes ermöglichen es, dass Daten erhalten bleiben, auch wenn ein Docker-Container gelöscht wird. Volumes sind auch eine praktische Möglichkeit, Daten zwischen dem Host und dem Container auszutauschen.
Image Ein Docker-Image ist eine schreibgeschützte Vorlage, die von der Docker-Engine benutzt wird, um einen Container zu erzeugen.

Speicherabbild eines Containers

  • Das Image selbst besteht aus mehreren Layern, die schreibgeschützt sind und somit nicht verändert werden können
  • Ein Image ist portabel, kann in Repositories gespeichert und mit anderen Nutzern geteilt werden
  • Aus einem Image können immer mehrere Container gestartet werden
Container Docker-Container sind isolierte Ausführungseinheiten für Anwendungen und ihre Abhängigkeiten

Aktive Instanz eines Images

  • Der Container wird also gerade ausgeführt und ist beschäftigt
  • Sobald der Container kein Programm ausführt oder mit seinem Auftrag fertig ist, wird der Container automatisch beendet
Layer Teil eines Images und enthält einen Befehl oder eine Datei, die dem Image hinzugefügt wurde
  • Anhand der Layer kann die ganze Historie des Images nachvollzogen werden
Dockerfile Beschreibung zur Erstellung eines Docker-Container
  • Textdatei, die mit verschiedenen Befehlen ein Image beschreibt
  • werden bei der Ausführung abgearbeitet und für jeden Befehl wird ein einzelner Layer angelegt
Repository Satz gleichnamiger Images mit verschiedenen Tags, zumeist Versionen
Registry Verwaltung von Repositories (Docker Hub, Artifactory, ...)

Bibliotheken

Begriff Beschreibung
libcontainer Schnittstelle zu den Grundfunktionen von Docker
libswarm Schnittstelle, um Docker-Container zu steuern
libchan Einfache („light weighted“) Kommunikation zwischen Prozessteilen und Prozessen

Aufbau und Funktionen

„Build, Ship and Run Any App, Anywhere“
"Bild: Virtuelle Maschinen und Docker-Container im Vergleich"
Während jede virtuelle Maschine ein eigenes Betriebssystem startet, teilen sich Docker-Container den Kernel des Host-Systems

Unter diesem Motto bewirbt die quelloffene Container-Plattform Docker eine flexible, ressourcensparende Alternative zur Emulation von Hardware-Komponenten auf Basis virtueller Maschinen (VMs)

  • Während die klassische Hardware-Virtualisierung darauf beruht, mehrere Gastsysteme auf einem gemeinsamen Host-System zu starten, werden Anwendungen bei Docker mithilfe von Containern als isolierte Prozesse auf ein und demselben System ausgeführt
  • Man spricht bei der containerbasierten Server-Virtualisierung daher auch von einer Operating-System-Level-Virtualisierung

Der Vorteil containerbasierter Virtualisierung liegt somit darin, dass sich Anwendungen mit unterschiedlichen Anforderungen isoliert voneinander ausführen lassen, ohne dass dafür der Overhead eines separaten Gastsystems in Kauf genommen werden muss

  • Zusätzlich können Anwendungen mit Container plattformübergreifend und in unterschiedlichen Infrastrukturen eingesetzt werden, ohne dass diese an die Hard- oder Software-Konfigurationen des Hostsystems angepasst werden müssen

Docker ist das bekannteste Software-Projekt, das Anwendern und Anwenderinnen eine auf Containern basierende Virtualisierungstechnologie zur Verfügung stellt

  • Die quelloffene Plattform setzt dabei auf drei grundlegende Komponenten: Um Container auszuführen, brauchen Anwender lediglich die Docker-Engine sowie spezielle Docker-Images, die sich über das Docker-Hub beziehen oder selbst erstellen lassen

Motivation

Vereinfachte Bereitstellung von Anwendungen
  • Container, die alle nötigen Pakete enthalten leicht als Dateien transportieren und installieren lassen
  • Geringerer Overhead durch geteilten Host-Kernel
  • Schnelle Start- und Stopzeiten
  • Hohe Dichte isolierter Instanzen pro Host
  • Prozess- und Abhängigkeitsisolation (Namespaces, cgroups)
  • Reproduzierbare Laufzeitumgebungen durch unveränderliche Images
  • Portabilität über unterschiedliche Hosts und Plattformen
  • Feingranulares Ressourcen- und Zugriffsmanagement
  • Vereinfachtes Lebenszyklus-Management
Container gewährleisten

Trennung und Verwaltung der auf einem Rechner genutzten Ressourcen

  • Code
  • Laufzeitmodul
  • Systemwerkzeuge
  • Systembibliotheken
  • alles was auf einem Rechner installiert werden kann

Container

Sandbox-Prozess

Ein Container ist ein Sandbox-Prozess, der auf einem Host-Computer ausgeführt wird und von allen anderen auf diesem Host-Computer ausgeführten Prozessen isoliert ist

  • Diese Isolierung nutzt Kernel-Namespaces und cgroups, Funktionen, die es in Linux schon seit langem gibt
  • Docker macht diese Funktionen zugänglich und einfach zu verwenden
  • Ein ist Container eine lauffähige Instanz eines Images
Container werden über die Docker-API oder die Befehlszeilenschnittstelle
  • erstellt
  • gestartet
  • angehalten
  • verschoben
  • gelöscht
Er kann auf lokalen oder virtuellen Maschinen ausgeführt oder in der Cloud bereitgestellt werden
  • Er ist portabel (und kann auf jedem Betriebssystem ausgeführt werden)
  • Er ist von anderen Containern isoliert und führt seine eigene Software, Binärdateien, Konfigurationen usw
Erweiterte Form von chroot
  • Das Dateisystem wird aus einem Image bereitgestellt
  • Allerdings bietet der Container eine zusätzliche Isolation, die mit chroot nicht möglich ist
Siehe auch

Bereitstellung

Image oder Dockerfile
  • Fertige Images
  • Dockerfiles
    • Anweisungen zum Erzeugen eines Images (Dockerfiles) im Projekt verteilen
    • Dockerfiles können gut in Projekt-Repositoies bereitgestellt werden

Fertige Images

DockerHub bietet fertige Images

  • Ein solches gestartetes Image nennt sich dann Container und enthält beispielsweise Dateien, die in den Container gemountet oder kopiert werden
  • Man kann auch eigene Images bauen, indem man eine entsprechende Konfiguration (Dockerfile) schreibt
  • Jeder Befehl bei der Erstellung eines Images erzeugt einen neuen Layer, die sich dadurch mehrere Images teilen können

In der Konfiguration einer Gitlab-CI-Pipeline kann man mit image ein Docker-Image angeben, welches dann in der Pipeline genutzt wird

Docker Images

Ähnlich wie virtuelle Maschinen basieren Docker-Container auf Images

Schreibgeschützte Vorlage

Dieses isolierte Dateisystem wird von einem Image bereitgestellt, und das Image muss alles enthalten, was zur Ausführung einer Anwendung erforderlich ist - alle Abhängigkeiten, Konfigurationen, Skripte, Binärdateien und so weiter.

Portables Abbild eines Containers

Als wird ein Docker-Image in Form einer Textdatei beschrieben – man spricht von einem Dockerfile

  • Soll ein Container auf einem System gestartet werden, wird zunächst ein Paket mit dem jeweiligen Image geladen – sofern dieses nicht lokal vorliegt
  • Das geladene Image stellt das für die Laufzeit benötigte Dateisystem inklusive aller Parameter bereit
  • Ein Container kann als laufender Prozess eines Images betrachtet werden
Siehe auch

Docker-Engine

Mit Docker-Befehlen können Anwenderinnen und Anwender Software-Container direkt aus dem Terminal starten, stoppen und verwalten

  • Die Ansprache des Daemon erfolgt über das Kommando dockerund Anweisungen wie build (erstelle), pull (lade herunter) oder run (starte)
  • Client und Server können sich dabei auf dem gleichen System befinden
  • Alternativ steht Anwendern die Möglichkeit offen, einen Docker-Daemon auf einem anderen System anzusprechen
  • Je nachdem, welche Art von Verbindung aufgebaut werden soll, erfolgt die Kommunikation zwischen Client und Server über die REST-API, über UNIX-Sockets oder eine Netzwerkschnittstelle

Komponenten

Zusammenspiel der Docker-Komponenten

"Bild: Schematische Darstellung der Docker-Architektur"
Die Docker-Architektur basiert auf einem Zusammenspiel aus Client (Terminal), Server (Docker-Daemon) und Registry (Docker-Hub)
Beispiel
docker build
docker pull
docker run
docker build

Das Kommando docker build weist den Docker-Daemon an, ein Image zu erstellen (gepunktete Linie)

Soll das Image nicht selbst erstellt, sondern aus einem Repository im Docker-Hub geladen werden, kommt das Kommando docker pull zum Einsatz (gestrichelte Linie)

  • Wird der Docker-Daemon via docker run angewiesen, einen Container zu starten, prüft das Hintergrundprogramm zunächst, ob das entsprechende Container-Image lokal vorliegt
  • Ist dies der Fall, wird der Container ausgeführt (durchgezogene Linie)
  • Kann der Daemon das Image nicht finden, leitet dieser automatisch ein Pulling aus dem Repository ein

Betriebssysteme

Virtualisierung mit Linux

Docker auf die Virtualisierung mit Linux ausgerichtet

Container und Virtuelle Maschinen

Varianten
  • Hardware
  • Betriebssystem
    • Linux, FreeBSD, macOS, Windows, …
  • Virtualisierung

Herkömmliche Virtualisierung

Im rechten Bild wird eine herkömmliche Virtualisierung mit virtuellen Maschinen (VM) dargestellt

  • Dabei wird in der VM ein komplettes Betriebssystem (das "Gast-Betriebssystem") installiert und darin läuft dann die gewünschte Anwendung
  • Die Virtualisierung (VirtualBox, VMware, ...) läuft dabei als Anwendung auf dem Host-Betriebssystem und stellt dem Gast-Betriebssystem in der VM einen Rechner mit CPU, RAM, zur Verfügung und übersetzt die Systemaufrufe in der VM in die entsprechenden Aufrufe im Host-Betriebssystem
  • Dies benötigt in der Regel entsprechende Ressourcen: Durch das komplette Betriebssystem in der VM ist eine VM (die als Datei im Filesystem des Host-Betriebssystems liegt) oft mehrere 10GB groß
  • Für die Übersetzung werden zusätzlich Hardwareressourcen benötigt, d. h. hier gehen CPU-Zyklen und RAM "verloren"
  • Das Starten einer VM dauert entsprechend lange, da hier ein komplettes Betriebssystem hochgefahren werden muss
  • Dafür sind die Prozesse in einer VM relativ stark vom Host-Betriebssystem abgekapselt, so dass man hier von einer "Sandbox" sprechen kann: Viren o.ä
  • können nicht so leicht aus einer VM "ausbrechen" und auf das Host-Betriebssystem zugreifen (quasi nur über Lücken im Gast-Betriebssystem kombiniert mit Lücken in der Virtualisierungssoftware)

Container

Virtualisierung auf Containerbasis

Im linken Bild ist eine schlanke Virtualisierung auf Containerbasis dargestellt

  • Die Anwendungen laufen direkt als Prozesse im Host-Betriebssystem, ein Gast-Betriebssystem ist nicht notwendig
  • Durch den geschickten Einsatz von namespaces und cgroups und anderen in Linux und FreeBSD verfügbaren Techniken werden die Prozesse abgeschottet, d. h. der im Container laufende Prozess "sieht" die anderen Prozesse des Hosts nicht
  • Die Erstellung und Steuerung der Container übernimmt hier beispielsweise Docker
  • Die Container sind dabei auch wieder Dateien im Host-Filesystem
  • Dadurch benötigen Container wesentlich weniger Platz als herkömmliche VMs, der Start einer Anwendung geht deutlich schneller und die Hardwareressourcen (CPU, RAM, ...) werden effizient genutzt
  • Nachteilig ist, dass hier in der Regel ein Linux-Host benötigt wird (für Windows wird mittlerweile der Linux-Layer (WSL) genutzt; für macOS wurde bisher eine Linux-VM im Hintergrund hochgefahren, mittlerweile wird aber eine eigene schlanke Virtualisierung eingesetzt)
  • Außerdem steht im Container üblicherweise kein graphisches Benutzerinterface zur Verfügung
  • Da die Prozesse direkt im Host-Betriebssystem laufen, stellen Container keine Sicherheitsschicht ("Sandboxen") dar!

In allen Fällen muss die Hardwarearchitektur beachtet werden: Auf einer Intel-Maschine können normalerweise keine VMs/Container basierend auf ARM-Architektur ausgeführt werden und umgekehrt


Anhang

Siehe auch

Kategorien
Unterseiten
  1. https://docs.docker.com
  2. https://hub.docker.com/search
  3. https://de.wikipedia.org/wiki/Docker_(Software)
  4. https://www.hsbi.de/elearning/data/FH-Bielefeld/lm_data/lm_1359639/building/docker.html
  5. Offizielle Website
  6. Renaissance der Container-Virtualisierung mit Docker
  7. Einführung und Praxisbeispiele / Übersicht Docker und Container-Virtualisierung