Benutzer-Werkzeuge

Webseiten-Werkzeuge


docker

Bestandteile

  • Client → Client der sich mit dem Docker Daemon verbindet
    • der Client und Daemon können auf verschiedenen Systemen laufen
  • Docker Daemon
    • Daemon der die Images und Container verwaltet

Befehle

Befehl Beschreibung
dockerDer Grundaufruf von Docker.
Dieser Eintrag dient nur dem listen von Optionen die direkt nach docker kommmen, nach diesen kommen dann die eigentlichen Befehle und deren Optionen.
Bsp:
docker -H=somehost.de:2375 run -d nginx

Würde auf einem entfernten Host somehost:2375 docker run mit der Option -d und Image nginx ausführen

Option Beschreibung
-H<Host:Port>Führt den Befehl auf einem anderen Host aus
docker run -d <Image-Name>:<Tag> <Command>Startet ein Image (falls nicht vorhanden wird es heruntergeladen) und ermöglicht initiale Konfiguration.
  • -d - detach. Per Default werden alle Ausgaben aus dem Container (stdout) auf der Konsole ausgegeben und ein schließen der Konsole hat die Beendigung des Containers zur Folge
  • Image-Name: Name des Image
  • Tag: Optional der Tag des Images
  • Command: Optional ein Befehl der im Image ausgeführt werden soll
    • dieser wird statt des im Image definierten cmd ausgeführt
    • ist im Image ein Entrypoint definiert, wird das was als Command spezifiziert wird als Parameter an den Befehl in Entrypoint angehängt → auf diese Art lassen sich Parameter zum auszuführenden Prozess setzen
Option Beschreibung
-dDetach. Per Default ist der Container mit der Konsole „verbunden“. Alle Ausgaben sind sichtbar, wird die Konsole beendet oder Ctrl+C gedrückt wird der Container beendet.
-tTerminal. Ausgaben auf stdout werden ausgegeben
-iInteraktiv. Eingaben im Terminal werden an Docker übertragen. Sinnvoll wenn man zum Beispiel eine Shell im Container gestartet hat. Es wird an stdin attached
-p <Host-Port>:<Container-Port>Port-Mapping → Mappt einen Port des Host-Systems auf einen Port des Containers → Port-Forwarding.

-p 8080:80
Mappt Port 8080 des Hostsystems auf Port 80 des Containers
-v <Source>:<Container dir>Volume → Mappt ein lokales Verzeichnis in ein Verzeichnis in einem Container.
Normalerweise sind Daten verloren, wenn der Container gelöscht wird (zum Beispiel eine Datenbank), dadurch das man ein Volume auf ein Verzeichnis im Container mounted werden die Daten die in dieses Verzeichnis geschrieben werden praktisch auf dem host gespeichert.

  • Source:
    • Verzeichnis auf dem Host → dann wird dieses Verzeichnis auf das Ziel gemountet
    • Name → dann wird ein Volume (ein Verzeichnis mit dem gegebenen Namen unter /var/lib/docker/volumes/<Name> ggf. erstellt und dorthin gemountet
    • weggelassen (inkl. dem „:“) → es wird ein Nummernverzeichnis unter /var/lib/docker/volumes erstellt und dorthin gemountet
  • Container Dir:
    • das Verzeichnis im Container wohin gemountet werden soll.

Hinweis: Es sollte

--mount

verwendet werden, statt -v, da es präziser/ausführlichere Angaben ermöglicht

-e Variable=WertSetzt eine Umgebungsvariable (Environmentvariable) im Container auf einen bestimmten Wert.
Nützlich wenn bestimmte Dinge in der darin laufenden Applikation dynamisch gesetzt werden sollen
–name <Name>Gibt dem Container einen Namen.
Dieser kann alternativ zur ID benutzt werden in Befehlen
–entrypoint <Befehl>Überschreibt den im Image definierten Entrypoint.
Hinter dem Image angegebene (oder wenn nicht) in CMD im Image angegebene Parameter werden weiterhin an den Entrypoint angehängt
–cpus <Wert>Anzahl CPUs die der Container nutzen kann.
Es sind auch Nachkommastellen, auch unterhalb von 0 möglich → .5 → eine CPU zur Hälfte auslasten
–memory <Wert>Menge RAM die der Container maximal nutzen kann.
Es können Einheteiten wie 100m → 100 Megabyte genutzt werden.
Hinweis: Dies definiert das Maximum das ein Container nutzen kann, aber sichert nicht zu das so viel Speicher ggf. auch angefordert werden kann → sind mehrere Container/Prozesse auf dem Host am laufen, teilen diese sich den Speicher, ist der Speicher auf dem Host alle bekommt der Container keinen mehr.
–mountHängt ein Volume oder ein Verzeichnis in den Container ein - so wie -v.

docker run --mount type=<type>,source=<source>,destination=<destination> -d whatever

Die Optionen von –mount müssen hintereinander weg, ohne Leerzeichen angegeben werden.

Option Beschreibung
<type>
  • bind → ein Verzeichnis des Hosts wird als Verzeichnis im Container eingehängt
  • volume → ein Docker-Volume → Verzeichnis unter /var/lib/docker/volumes wird in den Container eingehängt
  • tmpfs → ein temporäres (nur im Speicher existentes) Dateisystem wird in den Container eingehängt. Dieses wird gelöscht sobald der Container gestoppt wird (ist für temporäre Dateien)
sourceAbhängig von type.
  • volume → Name den das volume haben soll. Optional, ansonsten wird ein numerischer Name vergeben
  • bind → Pfad zum Verzeichnis auf dem Host was in den Container gemountet werden soll
destinationPfad im Container in den gemountet werden soll
–link <Container-Name>:<Zielname>„Verlinkt“ macht einen existierenden Container von dem neu erstellten aus über den angegebenen Namen erreichbar.

Praktisch wird die /etc/hosts im neu erstellten Container geändert, so das er über <Zielname> den Container mit <Container-Name> erreichen kann.
Ein besserer Weg ist über docker compose, alle Maschinen eines Compose-Aufrufs befinden sich im gleichen Netzwerk und können sich über ihren Namen erreichen
–network <Netzwerkname>Bindet den Container an ein bestimmtes Netzwerk.

Per Default binden sich Container an die Docker-Default-Bridge (für gewöhnlich docker0).

Netzwerkname Beschreibung
noneKein Netzwerk
hostDas Hostnetzwerk. Alle Ports sind direkt „nach außen“ geführt. Sprich ein Port 8080 im Container erscheint direkt auf dem Host-Netzwerk-Interface. Port-Mapping ist hier nicht möglich
<irgendeinName>Ein spezifisches Netzwerk. Dieses muss zuvor mit docker network create erstellt worden sein
docker start <Container-ID/Name>Startet einen Container
docker stop <Container-ID/Name>Stoppt einen Container
docker rm <Container-ID/Name> Löscht einen Container.
Dieser muss ggf. gestoppt sein
docker psListet Container.
Per Default werden nur die laufenden (nicht gestoppten) gelistet.
Option Beschreibung
-aListet alle Container - auch die gestoppt sind
docker inspect <Container-ID/Name>Gibt weitere Details zu einem Container aus.

U.a. welche interne IP er nutzt
docker exec <Container-ID/Name> <Befehl> Führt einen Befehl auf einem laufenden Container aus.
Die Ausgabe wird auf dem Terminal ausgeben.
Option Beschreibung
-tTerminal → Attach auf stdout des Containers. Ausgaben des Container werden auf der Konsole ausgegeben
-iInteractive → Attache auf stdin des Containers. Eingaben die gemacht werden, werden an den Container weitergereicht

Beispiel:

docker exec 5efg cat /etc/*release*
Würde cat auf /etc/*release* im Container machen und die Release-Daten zurückgeben

docker exec -ti 5efg cat bash
Würde eine bash auf dem Container starten und die Eingaben und Ausgaben an meine lokale Terminal-Sitzung weiterleiten. Man kann dann auf dem Container arbeiten als wäre man lokal auf dessen Terminal

docker logs <Container-ID/-Name>Zeigt die Logs des Containers (was die Andwendung im Container nach stdout schreibt)
docker pull <Image-Name>:<Image-Tag>Kurzversion von docker image pull
docker rmi <Image-Name>:<Image-Tag>Kurzversion von docker image rm
docker image Kommando um mit Images zu arbeiten. Siehe nachfolgende Einträge
docker image rm <Image-Name>:<Image-Tag>Löscht das angegebene Image.
Das Image darf nicht in Verwendung sein.
Soll ein Image mit einem Tag was nicht „latest“ ist gelöscht werden muss das Tag angeben werden
docker image pull <Image-Name>:<Tag>Lädt ein Image herunter.
Startet aber im Gegensatz zu „docker run“ keinen Container mit diesem Image.
Wenn das Tag „latest“ genutzt werden soll braucht es nicht explizit angegeben zu werden
docker build [–file <Dockerfile>] -t <Image-Name>:<tag> Baut ein neues Image anhand eines Dockerfiles.
–file <Dockerfile> ist nur notwendig wenn das Dockerfile nicht den Namen „Dockerfile“ hat.
<tag> ist optional - wenn nicht angegeben wird es „latest“
docker push <Imagename>Veröffentlicht ein Image in einer Registry (per Default in Docker-Hub).
Für Images die kein offizielles Produktimage ist muss man PersönlicherName/Image-Name oder Firmenname/Image-Name benutzen beim benennen des Images.
Der Name vor dem \ muss der Account-Name sein.
docker loginBevor man irgendetwas mit der Registry machen kann (zum Beispiel docker push) muss man sich in der Regel einloggen
docker history <Imagename>Zeigt die Layer und Veränderungen an einem Image an
docker composeVerwaltet mehrere Container anhand eines Compose-Files.

Unterbefehl Bedeutung
upSucht nach einer compose.yaml-Datei im aktuellen Verzeichnis und startet die darin enthaltenen Container und Netzwerke
docker volumeVerwaltung von volumes.
Volumes sind bleibender (persistent) Speicher die in den Container in ein Verzeichnis gemountet werden können (siehe docker run -v-Option). Container sind modifizierbar (Änderungen bleiben also erhalten), aber sobald der Container gelöscht wird sind die Änderungen weg → was z.B. bei Datenbanken ggf. unerwünscht ist.

Unterbefehl Beschreibung
create <Volume-Name>Erstellt ein neues Volume
docker networkVerwaltet die Netzwerke

Unterbefehl Beschreibung
create <Name>Erstellt ein Netzwerk mit dem <Namen>
Option Beschreibung
–driverWelcher Netzwerktreiber genutzt werden soll - optional.
Default: Bridge
  • bridge - Default, stellt ein Subnetz zur Verfügung was über eine Bridge mit dem Host verbunden ist
  • overlay - wird bei Docker Swarm genutzt
–subnetWelches Subnetz verwendet werden soll - otpional.
Wird es nicht angegeben vergibt Docker automatisch eins.
--subnet 127.2.0.0/16
inspect <Name>Gibt die Informationen zum entsprechenden Netzwerk zurück.

U.a. vergebene IPs, Default-Gateway, beteiligte Container
connect <Netzwerkname> <Containername> Verbindet einen existierenden Container mit einem zusätzlichen Netzwerk
disconnect <Netzwerkname> <Containername>Entfernt einen existierenden Container aus einem Netzwerk

Dockerfile

  • die Vorlage/der Satz der Anweisungen aus denen sich ein Image bauen lässt
  • für gewöhnlich heißt es Dockerfile
    • wenn es Dockerfile heißt reicht der Aufruf von „docker build“ aus um es zu bauen
    • sonst muss docker build –file <Dateiname> aufgerufen werden
      • guter Brauch ist es <Dateiname>.Dockerfile zu nutzen
  • Besteht aus „Instructions“ (Keywords) die eine Aktion definieren und Parametern zu diesen
  • Images bestehen aus Layern - jede Instruction erzeugt einen neuen Layer
    • ein Layer definiert die Unterschiede zur Summe der vorhergehenden Layer
    • Layer werden gecashed, schlägt ein Step fehl oder werden Steps eingefügt müssen die Steps davor nicht wiederholt werden, weil der Stand ja in Form der Layer noch vorhanden ist

FROM ubuntu:22.04

RUN apt-get update & apt install python3 python3-pip

COPY ./somescript.py /opt/somescript.py

CMD /opt/somescript.py

Instruction Bedeutung
FROM <Image-Name>:<Tag>Gibt an auf welchem Image das Image basieren soll.
Muss vorhanden sein.
Das Tag ist optional, wenn nicht angegeben wird „latest“ genommen
RUN <Command>Führt einen Befehl innerhalb des Images (was über FROM geladen wurde) aus.
Die Reihenfolge der Befehle wird beachtet.
Es können nur Befehle ausgeführt werden die zum jeweiligen Zeitpunkt auch Teil des Images sind (es spielt keine Rolle ob der Befehl auf dem Host existiert, er muss im Image vorhanden sein).
COPYKopiert eine lokale Datei in den Container.
Es wird vom Host in den Container kopiert
ENV <Variable>=WertSetzt eine Umgebungsvariable im Container auf einen bestimmten Wert.
„ENV EDITOR=vim“ würde die EDITOR-Umgebungsvariable auf vim setzen
EXPOSE <Portnummer>Ein bestimmter Port wird „freigegeben“.
Dieser Port ist dann über die interne IP des Containers erreichbar (es muss natürlich eine Anwendung im Container auf diesem Port lauschen)
CMD <Befehl>Der Befehl wird ausgeführt wenn der Container gestartet wird.

CMD Befehl Parameter1 Parameter2
oder als Liste:
CMD ["Befehl", "Parameter1", "Parameter2"]
Aber nicht so:
CMD ["Befehl Parameter1"]
In der Listen-Form müssen Befehle und jeder als eigener Eintrag aufgeführt werden.

ENTRYPOINT <Befehl>Im Gegensatz zu CMD werden Parameter die nach dem Containernamen angegeben werden angehängt.
Ein vorhandener CMD-Eintrag stellt die Default-Parameter zur Verfügung falls keine angegeben werden.

Beispiel:

CMD ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
ENTRYPOINT [mysql]
Obige Konfiguration würde mysql (Entrypoint) ausführen im Container und wenn keine Parameter bei docker run angegeben werden die Parameter in CMD an mysql übergeben.
docker run -d --name dbinstance mysql --character-set-server=latin1
hingegen würde nur –character-set-server=latin1 an den mysql-Aufruf übergeben.

Hinweis: Es muss die JSON-Syntax → also [„Parameter1=Value1“, „Parameter2=Value2“] benutzt werden

Näheres findet man hier: https://docs.docker.com/engine/network/

Compose.yaml

  • Ermöglicht starten, überwachen und verwalten eines Satzes zusammengehöriger Container
  • es gibt 3 Versionen dieser Dateien
    • Version 1
      • kennt die Container ohne übergeordnetes Serviec-Dictionary-Eintrag
      • alle Container werden der Default-Bridge zugeordnet
        • es muss link benutzt werden um Container miteinander zu „verknüpfen“
    • Version 2 und 3
      • haben einen Dictionary-Eintrag version: 2 bzw. version: 3
      • Container werden im service-Eintrag gelistet
      • Jedes Docker-File erzeugt ein neues Default-Netzwerk
        • Container können sich automatisch untereinander per Namen in diesem Netzwerk ansprechen
        • die Nutzung von link ist nicht notwendig
    • Version 3 unterstützt Docker Swarm

version: 3
services:
    webserver:
        image: "nginx:13.2"
        ports: 
            - "8080:80"
    myapp:
        build: ./myapp

Key Eltern-Element Typ Beschreibung
- DictionaryImaginäre-Root-Element
includerootlistBindet anderes Compose-File ein und führt sie gemeinsam mit diesem aus.
Liste von Strings (jede repräsentiert den Pfad zu einer Compose-Datei
versionrootintGibt die Version an - Beschreibung siehe in Stichpunkten oben. Ab Version 2 verpflichtend
servicsesrootDictionaryEnthält die Services aka. die Container die gestartet werden sollen.

Einträge sind die Namen der Container
<Name des Service>servicesDictionaryDefiniert die Eigenschaften des Service/Containers

Entspricht
docker --name <Name des Service>
image<Name des Service>stringImage welches für den Container genutzt werden soll.

Es muss als string angegeben werden. Wird ein Tag genutzt oder bestimmte Zeichen (wie zum Beispiel ein Tag angegeben und durch : getrennt) muss es in „“ gesetzt werden.

Entpspricht docker <Image-Name>
ports<Name des ServiceListHost-Port-Mappings.
Listeneinträge sind strings und müssen in „“ gesetzt werden → wegen des „:“ und weil es Ziffern sind
<Port auf Host>:<Port im Container>

Entspricht
 docker -p
build<Name des Services>StringKann statt Image angegeben werden und baut das Image beim ausführen von docker compose up.
Verzeichnis in dem sich das zu bauende Dockerfile befindet
depends_on<Name des ServiceListGibt an das der Container erst gestartet werden soll wenn ein oder mehrere andere Container gestartet wurden.
Die Liste gibt an auf welche Container gewartet werden soll.

Zum Beispiel muss zuerst der DB Container vor dem Application-Container gestartet werden (weil die Anwendung sich zur Datenbank verbinden muss). Dann wird beim Application-Eintrag ein depends_on-Eintrag mit „db“ angelegt.
networksrootDictionaryEnthält die Namen der Netzwerke.
<Netzwerk-name>networksDictionaryNetzwerk-Einträge.

Kann ein leeres Dictionary sein
<Netzwerkname>: 

dann sind keine weiteren Eigenschaften für das Netzwerk definiert und Default-Eigenschaften werden genutzt

<Netzwerk-Name><Name des Service>ListListe von Netzwerken (definiert in network-key unterhalb von root) denen der Container angehört.
Innerhalb dieser ist der Container über seinen Namen ansprechbar/erreichbar (Namensauflösung)

Funktionsweise

Namespaces (Kernel-Feature) werden genutzt um Prozesse und Netzwerke zu trennen.
Der Host sieht dabei die Prozesse die im Container laufen als ganz normale Prozesse, mit normaler ID.
Der Container sieht eine eigene PID 1 und seine eigenen Prozesse mit ansteigenden PIDs - die von den PIDs abweichen die die gleichen Prozesse auf dem Hostsystem haben.


Über cgroups (Kernel-Feature) kann die Nutzung von CPU und RAM eingeschränkt werden.
Effektiv wird die cgroup auf die Prozesse im Containers angewendet.

Layered Approach

  • Ein Image besteht aus Layern (Schichten)
  • Jeder Befehl im Dockerfile bildet eine eigene Schicht
  • die nächste Schicht speichert jeweils nur die Veränderungen gegenüber der vorhergehenden Schicht
  • ein Container bildet eine beschreibbare (für die Zeit die der Container existiert) Schicht oberhalb aller Schichten des Containers
  • Schichten werden als solche gespeichert (gecached)
    • hat den Vorteil das man wenn man das Dockerfile modifiziert oder basierend auf existierenden Schichten ein neues baut, nur die neuen/modifizierten Schichten neu erzeugen muss - die bereits existierenden werden einfach genommen wie sie sind

Volumes

Man kann Verzeichnisse, Volumes (letztendlich Verzeichnisse unter /var/lib/docker/volumes) und tmpfs (Volumes im Arbeitsspeicher die nur existieren solange der Container läuft) in den Container mounten.
Das ist sinnvoll wenn:

  • Viel auf geschrieben/gelesen werden muss in dem Verzeichnis
    • Container haben zwar einen beschreibbaren Layer, aber auf Grund des Copy-on-Write-Approaches (Dateien die verändert werden müssen zuerst kopiert werden und dann modifiziert (theoretisch, hängt vom Storage-Driver ab) relativ langsam ist
  • Daten permanent gespeichert werden sollen, unabhängig von der Existenz des Containers
    • alles was im Container gespeichert wird geht mit dem löschen (nicht dem stoppen) des Containers verloren

Ggf. kann man auch den Storage-Treiber für den Container ändern um mehr Schreibperformance innerhalb des Containers rauszuholen, besser ist aber Volumes/Mounts zu nutzen.

Dateien/Verzeichnisse

Datei/VerzeichnisBedeutung
/var/lib/dockerAlle Dateien die Docker dynamisch erzeugt
/var/lib/docker/imageImages
/var/lib/docker/containersJeder Container hat hier ein Verzeichnis.

U.a. Config, Logs usw. liegen hier
/var/lib/docker/volumesVolumes die per docker volume create erstellt werden befinden sich hier

Registry

Image beziehen

  • Standardmäßig wird von docker.io geladen

Von einer anderen Registrie laden:

docker login
docker run <Registrie-Name>/<Verzeichnis>/<Image>:<Tag>

  • docker login muss nur ausgeführt werden wenn ein Benutzer-Name und Passwort für den Zugang notwendig ist und auch nur einmal pro Sitzung
  • <Registrie-Name> → Name der Registrie - something.de
  • <Verzeichnis> → Verzeichnis, zum Beispiel wenn es nach Benutzern organisiert ist
  • <Image> → Name des gewünschten Images
  • <Tag> → Tag des Images

Image in private Registry pushen

docker tag <Imagename> <Host:Port>/<Pfad>/<Imagename>:<Tag>
docker login
docker push <NewImagename>

  • docker tag gibt einem Image einen (zusätzlichen) Namen. Der Name bei privaten Registries enthält den Namen der Registy
    • Host → Host, z.B. myregistry.de
      • kann auch localhost sein wenn die Registry auf dem gleichen Host läuft
    • Port → anzugeben wenn der Port nicht 5000 ist
    • Pfad → optional ein Pfad, z.B. myusername
    • Imagename → der Name des Images, z.B. meineApp
    • Tag → Optional ein Tag, z.B. testing
    • docker tag baseimage myregistry.de:5000/myusername/meineApp:testing
  • docker login
    • nur notwendig wenn die Registry eine Authentifizierung benötigt
  • docker push lädt das neue Image hoch
    • <NewImageName> = myregistry.de:5000/myusername/meineApp:testing
      • kompletter Name, inkl. Registry
      • so muss das Image auch per docker pull oder docker run angesprochen werden

Private Restry aufsetzen

  • Docker Registry ist als Image verfügbar → Resistry
  • es lauscht standardmäßig an Port 5000

Troubleshooting

Problem Beschreibung
docker.errors.NullResource: Resource ID was not provided
Eine Umgebungsvariable wurde nicht gesetzt (in der Regel werden Warnungen ausgegeben).

In der Regel hat irgend ein Image in docker-compose.yaml eine Variable im Namen die nicht aufgelöst werden kann
docker stop <Container ID>

stoppt Container nicht

docker rm -f containername
docker.txt · Zuletzt geändert: 2024/10/29 21:21 von root