Docker ist eine Open-Source-Plattform zur [[container|Containerisierung]] von Anwendungen. Es ermöglicht die Erstellung, Bereitstellung und Ausführung von Anwendungen in isolierten Containern, die unabhängig von der zugrunde liegenden Infrastruktur sind. Docker bietet eine standardisierte Methode zum Verpacken von Software und allen damit verbundenen Abhängigkeiten in ein einzelnes Paket, das als Docker-Image bezeichnet wird. Diese Images können dann auf jedem System ausgeführt werden, das Docker unterstützt. Docker basiert auf der Linux-Containertechnologie ([[LXC]]) und nutzt die Funktionen des Linux-Kernels, um isolierte Umgebungen, sogenannte Container, zu erstellen. Jeder Container enthält eine eigenständige und isolierte Umgebung, in der eine Anwendung und ihre Abhängigkeiten ausgeführt werden können. Die Isolation sorgt dafür, dass eine Anwendung und ihre Abhängigkeiten unabhängig von anderen Containern und dem Hostsystem ausgeführt werden können, was zu einer besseren Portabilität und Skalierbarkeit führt. Siehe auch [[kubernetes|Kubernetes]]. =====Hauptkomponenten===== * Docker-Image: Ein Docker-Image ist ein leichtgewichtiges, ausführbares Paket, das alles enthält, was zur Ausführung einer Anwendung benötigt wird, einschließlich des Betriebssystems, der Laufzeitumgebung, der Bibliotheken und der Anwendungsdateien selbst. Images werden durch sogenannte Dockerfiles definiert, die eine Reihe von Anweisungen enthalten, um die Konfiguration und Installation der Anwendungsschichten zu beschreiben. * Docker-Container: Ein Docker-Container ist eine Instanz eines Docker-Images. Er kann gestartet, gestoppt, verschoben und gelöscht werden. Container bieten eine isolierte Umgebung für die Ausführung einer Anwendung, wodurch Konflikte mit anderen Containern oder dem Hostsystem vermieden werden. Container können schnell erstellt und bereitgestellt werden, was eine effiziente Skalierung und Verteilung von Anwendungen ermöglicht. * Docker-Daemon: Der Docker-Daemon ist der Hintergrundprozess, der auf dem Hostsystem läuft und Docker-Befehle entgegennimmt. Er ist für die Erstellung, Ausführung und Verwaltung von Docker-Containern verantwortlich. Der Daemon kommuniziert mit dem Docker-Client, der über eine Befehlszeilenschnittstelle oder eine grafische Benutzeroberfläche verfügbar ist und dem Benutzer die Interaktion mit Docker ermöglicht. =====Dockerfile===== Ein Dockerfile ist eine Textdatei, die eine automatisierte Build-Anweisung für das Erstellen eines Docker-Images enthält. Dockerfiles werden verwendet, um Container-Images zu erstellen. Ein Dockerfile besteht aus einer Reihe von Anweisungen, die Docker verwendet, um ein Docker-Image zu erstellen. Jede Anweisung in einem Dockerfile führt eine bestimmte Aktion aus, z. B. das Hinzufügen von Dateien, das Ausführen von Befehlen oder das Festlegen von Umgebungsvariablen. Dockerfiles verwenden eine einfache Syntax und können mit grundlegenden Texteditoren erstellt und bearbeitet werden. Hier sind einige der gängigsten Anweisungen, die in einem Dockerfile verwendet werden: * FROM: Die FROM-Anweisung definiert das Basisimage, auf dem das neue Image basieren soll. Es kann sich um ein offizielles Docker-Image handeln, z. B. ein Betriebssystem wie Ubuntu oder Alpine, oder um ein benutzerdefiniertes Image, das von einem anderen Dockerfile abgeleitet wurde. * RUN: Die RUN-Anweisung führt Befehle innerhalb des Containers aus und erzeugt einen neuen Layer mit den Änderungen. Dies können Installationsbefehle, Kompilierungsschritte oder andere Befehle sein, die zur Einrichtung der Anwendungsumgebung erforderlich sind. * COPY: Die COPY-Anweisung kopiert Dateien oder Verzeichnisse vom Host in den Container. Dies wird häufig verwendet, um Anwendungsquellcode, Konfigurationsdateien oder andere Ressourcen in den Container zu übertragen. * WORKDIR: Die WORKDIR-Anweisung legt das Arbeitsverzeichnis innerhalb des Containers fest, in dem alle nachfolgenden Befehle ausgeführt werden. Dadurch können relative Dateipfade in den folgenden Anweisungen verwendet werden. * EXPOSE: Die EXPOSE-Anweisung gibt an, welche Ports der Container zur Kommunikation mit der Außenwelt öffnen soll. Diese Anweisung hat keine Auswirkung auf die tatsächliche Portöffnung, sondern dient als Dokumentation für den Entwickler. * CMD: Die CMD-Anweisung gibt die Standardbefehle an, die beim Starten eines Containers ausgeführt werden sollen. Es kann nur eine CMD-Anweisung in einem Dockerfile vorhanden sein. Wenn beim Starten des Containers zusätzliche Befehle angegeben werden, überschreiben sie die in der CMD-Anweisung angegebenen Befehle. * ENV: Die ENV-Anweisung in einem Dockerfile wird verwendet, um Umgebungsvariablen im Container zu definieren. Umgebungsvariablen sind Schlüssel-Wert-Paare, die in der Containerumgebung verfügbar sind und von der Anwendung oder dem System innerhalb des Containers genutzt werden können. * ENTRYPOINT: Die ENTRYPOINT-Anweisung in einem Dockerfile definiert den Standardbefehl oder das Skript, das beim Starten eines Containers ausgeführt wird. Der Befehl oder das Skript wird als ausführbare Datei innerhalb des Containers behandelt. * VOLUME: Die VOLUME-Anweisung in einem Dockerfile wird verwendet, um ein oder mehrere Volumes im Container zu definieren. Ein Volume ist ein Speicherbereich, der von einem Container genutzt wird, um Daten persistent zu speichern, auch wenn der Container beendet oder neu gestartet wird. # Verwenden des Python-Basisimages FROM python:3.9 # Setzen des Arbeitsverzeichnisses innerhalb des Containers WORKDIR /app # Kopieren der Anforderungen (requirements.txt) in den Container COPY requirements.txt . # Installation der Abhängigkeiten RUN pip install --no-cache-dir -r requirements.txt # Kopieren des Anwendungsquellcodes in den Container COPY . . # Exponieren des Ports, auf dem die Anwendung lauscht EXPOSE 8000 # Festlegen des Standardbefehls beim Starten des Containers CMD ["python", "app.py"] Den Container erstellen. docker build -t . docker run -dit -p 80:80 =====Docker-Compose===== Im Gegensatz zu einem einzelnen Dockerfile, das ein einzelnes Image definiert, ermöglicht Docker Compose die Definition und Konfiguration von Diensten, Netzwerken und Volumes für eine vollständige Anwendungsumgebung. Es verwendet eine einfache YAML-Datei, um die Konfiguration zu beschreiben. version: '3' services: webserver: image: httpd:latest networks: - my-network ports: - 80:80 volumes: - ./html:/usr/local/apache2/htdocs/ depends_on: - database database: image: mariadb:latest networks: - my-network environment: - MYSQL_ROOT_PASSWORD=secret - MYSQL_DATABASE=mydatabase - MYSQL_USER=myuser - MYSQL_PASSWORD=mypassword volumes: - db-data:/var/lib/mysql volumes: db-data: networks: my-network: ====Deployments==== Um einen Load-Balanced Cluster mit mehreren Instanzen einer Anwendung zu erstellen, kannst du die Deploymentfunktion von Docker Compose verwenden. Somit laufen 3 Instanzen der Anwendung. Fällt eine aus, wird automatisch ein neuer Container gestartet. version: '3' services: app: image: myapp:latest ports: - 80:80 deploy: mode: replicated replicas: 3 update_config: parallelism: 2 delay: 10s restart_policy: condition: any Deployment starten/stoppen // Im Verzeichnis wo die docker-compose.yaml Datei liegt sudo docker compose [-f ] up -d sudo docker compose down =====Volumes===== Docker Volumes werden verwendet, um Daten zwischen Containern und dem Host-Betriebssystem auszutauschen und um sicherzustellen, dass Daten auch dann erhalten bleiben, wenn Container neu erstellt oder aktualisiert werden. Es sind sozusagen virtuelle Festplatten für Container. * Named Volumes: Named Volumes sind Volumes, die einen Namen haben und vom Docker-Daemon verwaltet werden. Sie sind einfach zu verwenden und können leicht zwischen Containern geteilt werden. * Host-mounted Volumes: Host-mounted Volumes ermöglichen es, einen Pfad auf dem Host-Betriebssystem als Volume-Mountpunkt zu verwenden. Dies ermöglicht eine direkte Verbindung zwischen dem Host und dem Container, wodurch Daten schnell ausgetauscht werden können. Allerdings sind Host-mounted Volumes weniger portabel, da sie von der spezifischen Konfiguration des Hosts abhängig sind. * Anonymous Volumes: Anonymous Volumes sind temporäre Volumes, die während der Laufzeit des Containers erstellt werden und keinen expliziten Namen haben. Sie werden automatisch von Docker erstellt und sind für einzelne Container reserviert. Ein Volume erstellen kann man mit docker volume create myvolume Mit dem Parameter --mount kann man ein Volume in einen Container mounten. Mit dem Parameter -v kann man einen Pfad am Host in einen Mountpoint am Container mounten. docker run -dit --mount source=,target= ubuntu docker run -dit -v : ubuntu =====LVM===== Vor der Installation bzw Inbbetriebnahme von Docker das [[LVM]] anlegen. sudo mount /dev/docker_vg_lv0 /var/lib/docker In der fstab /dev/docker-vg/lv0 /var/lib/docker ext4 defaults 0 2 =====Netzwerke===== Docker Networking unterstützt verschiedene Netzwerkmodelle, um den unterschiedlichen Anforderungen von Anwendungen gerecht zu werden. ^Name^Beschreibung^ |none|todo| |Host|Das Host-Netzwerkmodell verwendet das Netzwerk des Docker-Hosts direkt für die Container. Container, die das Host-Netzwerk verwenden, haben Zugriff auf alle Netzwerkressourcen des Hosts, einschließlich der Netzwerkschnittstellen und Ports. Dieses Modell bietet eine maximale Leistung, kann aber die Isolation zwischen Containern beeinträchtigen.| |Bridge|Ein Bridge-Netzwerk ist das Standardnetzwerkmodell von Docker. Es erstellt ein isoliertes Netzwerk für Container auf dem Docker-Host und ermöglicht die Kommunikation zwischen Containern über einen gemeinsamen Bridge-Dienst. Bridge-Netzwerke sind standardmäßig in Docker aktiviert und bieten eine einfache Möglichkeit, Container zu verbinden.| |Overlay|Overlay-Netzwerke werden verwendet, um Container über mehrere Docker-Hosts hinweg zu verbinden. Sie ermöglichen es Containern, über Host-Grenzen hinweg zu kommunizieren und eine skalierbare, verteilte Anwendung zu erstellen. Overlay-Netzwerke verwenden spezielle Protokolle wie VXLAN oder IPSec, um Container über das gesamte Cluster hinweg zu vernetzen.| |MacVlan|Das macvlan Netzwerkmodell ermöglicht es Containern, eine eigene MAC-Adresse zu haben und direkt mit dem physikalischen Netzwerk zu kommunizieren. Jeder Container erhält eine eindeutige MAC-Adresse, die von der des Hosts abweichen kann. Dies ermöglicht es Containern, direkt auf das physische Netzwerk zuzugreifen und mit anderen Geräten zu kommunizieren, als ob sie direkt an das physische Netzwerk angeschlossen wären.| |IpVlan|Das ipvlan Netzwerkmodell ist ähnlich wie das macvlan Modell, jedoch auf IP-Ebene. Es ermöglicht es Containern, eigene IP-Adressen zu haben und direkt mit dem physikalischen Netzwerk zu kommunizieren. Jeder Container erhält eine eindeutige IP-Adresse, die von der des Hosts abweichen kann.| Mit docker network create -d docker network inspect docker network rm kann man ein neues erstellen. Ein Container Interface an ein Netzwerk binden kann man mit dem Parameter --network. docker run -dit --name test --network mynetwork ubuntu Ein Netzwerk von einem Container entfernen oder ändern kann man mit docker network disconnect docker network connect =====Traefik===== [[Traefik]] ist ein Reverse [[Proxy]] um [[Container]] über das Internet erreichbar zu machen. =====Installation===== Docker [[https://docs.docker.com/engine/install/|Installation]]. curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh ====Ubuntu==== # update packages sudo apt-get update # add pgp key for signed docker repository sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerprint 0EBFCD88 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" # update again sudo apt-get update # install docker sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ====WSL2==== # Install Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh sudo usermod -aG docker $USER # Install Docker Compose v2 sudo apt-get update && sudo apt-get install docker-compose-plugin # Sanity check that both tools were installed successfully docker --version docker compose version # Using Ubuntu 22.04 or Debian 10 / 11? You need to do 1 extra step for iptables # compatibility, you'll want to choose option (1) from the prompt to use iptables-legacy. sudo update-alternatives --config iptables =====Docker Daemon===== nano /etc/docker/daemon.json { "bip": "172.17.1.1/24", "ipv6": false, "storage-driver": "devicemapper", "storage-opts": [ "dm.basesize = 41G", "dm.thinpooldev=/dev/mapper/docker--vg-thinpool", "dm.use_deferred_removal=true" ] } =====Usage===== docker pull docker images docker rmi -f docker image prune docker inspect docker container diff // see changes from base image // see https://docs.docker.com/engine/reference/commandline/run/ docker run -dit --name --hostname -p : --mount source=,target=,readonly -v : --> -it - interactive, root terminal --> -p - port mapping ext:int --> -d - detach console --> --name - set container name --> --mount mount a docker-volume --> -v - mount a host folder : --> --network - connect to a specific docker-network --> --cpus=0.1 - use 1 % of cpu --> -m 512m - use max 512 bytes of memory --> --cpu-shares=2000 - operations per cycle? --> -e VAR=1 - set environment variable // change a running container using a snapshot docker commit docker run -dit // start with same settings as setup docker start // befehl auf laufendem host ausführen docker exec docker attach sudo docker exec -it /bin/bash # ctrl + p - ctrl q ==> detach (nur mit -ti)? docker start docker stop docker restart docker rename docker container ls docker ps -a docker rm docker container prune // remove all "status=exited" containers // volumes docker volume create --name testvol docker volume inspect test-vol docker volume rm test-vol docker run -dit --mount source=test-vol,target=/mount/test,readonly docker run -dit -v test-vol:/mount/test // networking docker network create -d bridge MyBridgedNetwork docker network connect docker network inspect docker network connect docker network disconnect =====Docker Swarm Cluster===== Als erstes erstellt man mit dem Befehl docker swarm init --advertise-addr ein Kontrollnode. Am Ende wird **ein Token** angezeigt, diesem gut merken! Möchte man weitere Nodes zu dem Cluster hinzufügen, führt man auf den jeweiligen Nodes den Befehl docker swarm join --token aus. Mit dem Befehl docker node ls werden alle Nodes eines Clusters angezeigt. =====Links===== * [[https://www.redhat.com/de/topics/containers/what-is-docker|RedHat - Was ist Docker]] * [[https://www.youtube.com/playlist?list=PLYxzS__5yYQlzv9_z1eZmZY8dzMlQFbaH|First steps - Youtube Playlist]] * [[https://www.digitalocean.com/community/tutorials/how-to-build-and-deploy-a-flask-application-using-docker-on-ubuntu-20-04|Building your first app]] * https://docs.docker.com/engine/reference/commandline/exec/ * https://docs.docker.com/engine/install/linux-postinstall/ * [[https://github.com/docker-library/official-images|How to build official images]]