Docker ist eine Open-Source-Plattform zur 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.
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:
# 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 <containername> . docker run -dit -p 80:80 <containername>
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:
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 <yml-filename>] up -d sudo docker compose down <deployment-name>
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.
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=<docker-volume>,target=<container-mountpoint> ubuntu docker run -dit -v <host-path>:<container-path> ubuntu
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
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 <driver> <network-name> docker network inspect <network-name> docker network rm <network-name>
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 <network-name> <container-name> docker network connect <network-name> <container-name>
Docker Installation.
curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
# 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
# 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
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" ] }
docker pull <image> docker images docker rmi -f <image-id> docker image prune docker inspect <container> docker container diff <container> // see changes from base image // see https://docs.docker.com/engine/reference/commandline/run/ docker run -dit --name <container-name> --hostname <hostname> -p <ext-port>:<int-port> --mount source=<vol>,target=<mountpoint>,readonly -v <volume>:<mountpoint> <image> <commands> --> -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 <folder>:<mountpoint> --> --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 <container> <new-image-name> docker run -dit <new-image-name> // start with same settings as setup docker start <container> // befehl auf laufendem host ausführen docker exec <container> <commands> docker attach <container> sudo docker exec -it <container> /bin/bash # ctrl + p - ctrl q ==> detach (nur mit -ti)? docker start <container> docker stop <container> docker restart <container> docker rename <oldname> <newname> docker container ls docker ps -a docker rm <container> 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 <image> docker run -dit -v test-vol:/mount/test <image> // networking docker network create -d bridge MyBridgedNetwork docker network connect <options> <network> <container> docker network inspect docker network connect <network> <container> docker network disconnect <network> <container>
Als erstes erstellt man mit dem Befehl
docker swarm init --advertise-addr <manager-ip>
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 <swarm-token> <manager-node-ip>
aus. Mit dem Befehl
docker node ls
werden alle Nodes eines Clusters angezeigt.