Einführung Docker
Markus Brunsch / April 2022
Docker Container Plattform
Docker ist ein Open Source-Projekt zur Automatisierung der Bereitstellung von Apps als mobile, eigenständige Container, die in der Cloud oder lokal ausgeführt werden können. Docker ist darüber hinaus ein Unternehmen, das diese Technologie fördert und weiterentwickelt und mit Cloud-Anbietern, Linux und Windows kompatibel ist.
Dabei stellen Container eigenständige und abgeschottete Laufzeitumgebungen für Anwendungen verschiedenster Art dar. Container und die dazugehörigen Container Images basieren auf dem OCI (Open Container Initiative) Standard und sind somit nicht nur mit Docker kompatiebel. Docker ist vielmehr nur das zugehörige Verwaltungswerkzeug, um die darunterliegende Container Infrastruktur zu verwalten. Docker bietet dabei die Möglichkeiten, Container anzulegen, zu starten / stoppen oder zu löschen. Es können neue Images erstellt und bestehende Images verwaltet werden, lokal oder remote in sogenannten Container Registries (z.B. hub.docker.com)
Containervirtualisierung
Containervirtualisierung beschriebt eine Form der Virtualisierung beider auf dem Host System mittels PID Namespacing im Linux-Kernel eine eigene Laufzeitumgebung geschaffen wird. Inder Anwendungen abgeschottet vom restlichen System betrieben werden können.
Der Vorteil dieser Virtualisierungesmethode, ist der um ein Vielfaches verringerter Overhead im Vergleich zu KVM. Da bei einer Container Virtualisierung im direkten Vergleich der Kernel des Host OS verwendet wird und die Ressourcen des Systems nur abstrahiert und nicht virtualisiert werden.
Somit kann bei Containern auf ein eigenes Betriebssystem im klassischen Sinne verzichtet werden. Es muss lediglich eine Laufzeitumgebung mitgegeben werden, um die entsprechende Anwendung ausführen zu können. Somit kann die Hardware optimal ausgenutzt und der Wartungsaufwand deutlich reduziert werden.
Technologien, die auf diese Art der Virtualisierung zurückgreifen, sind. LXC und OCI Container.
Bei LXC Containern wird ein leichtgewichtiges Linuxsystem erzeugt, das über traditionelle Methoden administriert / verwaltet wird z.B. SSH.
OCI Container verfolgen einen anderen Weg, hier geht es darum, sehr leichtgewichtige System für die Cloud bereitzustellen. Hier liegt der Fokus auf Sicherheit, Performance und Fehlerminimierung.
Die Container sind weitergehend dazu auch im Hinblick auf die 12 Faktoren im Cloudumfeld designet, sie sind vorzugsweise Stateless, skalierbar und im Fehlerfall schnell austauschbar. Eine manuelle Fehlerbehebung eines einzelnen “bad” Containers ist hier nicht vorgesehen. Vielmehr werden die Container einfach schnell gegen einen neuen funktionsfähigen Container ausgetauscht.
Gerade im Hinblick auf Kubernetes, ist diese Art der Containerverwaltung die Grundlage eines solchen Konzepts.
Moby Project
Das Moby Projekt zu finden auf Github, stellt die Library dar, die von Docker für die Interaktion mit dem System verwendet wird. Hier ist z.B. der Image Build Prozess abgebildet.
ContainerD
ContainerD ist eine OCI standardisierte Container Laufzeitumgebung. Diese ist für den eigentlichen Betrieb der Container verantwortlich und steuert diesen eigenständig.
containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc.
Zu finden ist das Projekt bei Github
OCI - Open Container Initiative
Die Open Container Initiative verabschiedet Standards im Bereich Containering. Darunter fallen die Spezifikationen der Container und deren Images, damit diese zu den verschiedenen Systemen interkompatibel sind.
runc
runc
is a CLI tool for spawning and running containers on Linux according to the OCI specification.
Wird von Docker im Hintergrund verwendet, um Container anzulegen und zu verwalten.
Zu finden auf Github
Docker Image Erstellen
Um ein Docker Image zu erstellen, wird mit sogenannten Dockerfiles das Image definiert. Dieses Dockerfile wird dann dem Build Agent übergeben, der dann aus dem übergebenen Dockerfile ein OCI Container Image erstellt.
In der Regel sind Dockerfiles in 3 Bereiche aufgeteilt.
Import: Hier werden OS Images (Debian, Alpine, Ubuntu, …) angegeben bzw. Base Images (Frameworks wie Java, dotNet, NodeJS oder Python) damit wird die Laufzeitumgebung festgelegt.
Installation: Hier wird die Installationsroutine der Software angegeben z.B. Download von Artefakten oder Kompilierung der Software.
Entrypoint: Hier wird der Startpunkt der Anwendung festgelegt.
Ein beispielhaftes Dockerfile sieht in etwa so aus:
FROM alpine:3.4
RUN apk update && apk add \
curl \
git \
vim
RUN wget http://myapp.com/run && chmod +x run
ENTRYPOINT['run']
Im Anschluss kann dann das Dockerfile zu einem Image gebaut werden docker build .
Docker Image Verwaltung
-
Anzeigen der lokal geladenen Images
[root@host ~]$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ngoduykhanh/powerdns-admin latest 938d8ef921ab 5 months ago 157MB psitrax/powerdns latest 720c44942097 6 months ago 63.7MB redis latest 08502081bff6 6 months ago 105MB mariadb latest 104f4e7cbe83 6 months ago 408MB ubuntu latest 7e0aa2d69a15 8 months ago 72.7MB freinet/powerdns latest 8fdce2cafa4e 12 months ago 55.5MB jorgedlcruz/zimbra latest 79403a039239 4 years ago 302MB
-
Löschen eines Images
[root@host ~]$ docker image rm 79403a039239 Untagged: jorgedlcruz/zimbra:latest Untagged: jorgedlcruz/zimbra@sha256:5d2548365fd079ba51e87c7a8f54feacfce23d370f49d66311632eb2a422b026 Deleted: sha256:79403a039239add5f60084f7ff2203fe145b3f8f86e83a925359e06e38cb437f Deleted: sha256:c07d6c55520b0908e868f8a85d2b8928616008a8c26d27bd61f425ce1a2058c6 Deleted: sha256:e2a75e141e320208ce68299d7f72e1fe46a1c9b8a5702256ea45ef94ae80cca0 Deleted: sha256:1f0250b6692ee176c5e1978ee2aa921d724873b9c5fa8ec19be04c640660393d Deleted: sha256:7f6e10c2ecea8d277d1a8c7c618e7dd93e5e0357e68d6e88f1f1ab26de03e59a Deleted: sha256:ec1fd849ff0a8f0aa2fd1acc29ad5dabbc79b89f63b74a4f54e31a7b0a100aa1 Deleted: sha256:e3f6dffa20cf36460d23bfb22e17be6e5339891f8537f32db79887caf832048b Deleted: sha256:c213ffdc9f7032702de5a8e9045fcce2353b7221ef6bf4509e02005cfc858f58 Deleted: sha256:3fddf55a451aa43707518f2d8788c12ee5eb1f1e3075433f5bcf4d445d5c275d Deleted: sha256:0f5ff0cf6a1c53f94b15f03536c490040f233bc455f1232f54cc8eb344a3a368
-
Herunterladen eines neuen Images
[root@host ~]$ docker pull alpine:latest latest: Pulling from library/alpine 59bf1c3509f3: Pull complete Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300 Status: Downloaded newer image for alpine:latest docker.io/library/alpine:latest
Docker Container Verwaltung
-
Auflistung der Container in auf dem System
[root@host ~]$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5793bbed585b mariadb:latest "docker-entrypoint.s…" 28 hours ago Exited (0) 21 hours ago elastic_agnesi 13102f675ad0 mariadb:latest "docker-entrypoint.s…" 3 months ago Up 2 hours 3306/tcp docker-db-1 0e98170a7024 ngoduykhanh/powerdns-admin:latest "entrypoint.sh gunic…" 3 months ago Exited (0) 3 months ago powerdns_admin a0f8b16bc64a psitrax/powerdns:latest "/entrypoint.sh" 3 months ago Exited (143) 3 months ago powerdns cc6847b3c8a9 ubuntu "bash" 6 months ago Exited (0) 6 months ago recursing_mendeleev 7fc041db6bc6 redis:latest "docker-entrypoint.s…" 6 months ago Exited (0) 6 months ago lucid_kepler be47035dd9d3 mariadb:latest "docker-entrypoint.s…" 6 months ago Exited (0) 2 months ago mariadb
Mit dem
-a
Parameter lassen sich auch die abgeschalteten Container anzeigen.
- Starten neuer Container
Im Beispiel: Startet einen Nginx Container auf Port 8080
docker run -d -p 8080:80/tcp --name=webserver --restart=always nginx:latest
Die verwendeten Parameter Parameter | Funktion | ——– | ——– | -d | Container im Hintergrund Starten -p 8080:80/tcp | TCP Portfreigabe von 8080 extern nach 80 intern –name | Namen des Containers festlegen –restart=always | Setzt die Restart Policy auf immer starten
Genauere Infos und Referenzen in der Docker Dokumentation
- Löschen eines Containers
docker container rm -f 5793bbed585b
Container ID oder Container Name
Verwendeter Paramerter
-f
(Force) Löscht den Container auch im aktiven Zustand.
-
Vorhandenen Container Starten / Stoppen / Neustarten
- Starten
docker container start [ContainerID]
- Stoppen
docker container stop [ContainerID]
- Neustarten
docker container restart [ContainerID]
- Starten
Docker Compose
Docker Compose ermöglicht es, mehrere Container in einem Deployment zusammenzufassen und die Ressource in diesem Deployment gegenüber anderen Containern abzuschirmen, die dafür notwendigen Schritte werden alle automatisch von Docker Compose übernommen.
Docker Compose benötigt eine sogenannte docker-compose.yml
Datei, diese Datei enthält die Konfiguration des Deployments.
Durch Docker Compose werden die folgenden Ressourcen verwaltet:
- Container
- Overlaynetzwerke
- Volumes
Ein typisches Usecase für Docker Compose wäre eine Webanwendung, bei der eine Datenbank, ein Webserver und ein Anwendungsserver benötigt werden. Dabei steuert Docker Compose die Erstellung der Container und deren persistenten Daten, die Erstellung eines Cloudnetzwerks sowie die automatische Zuweisung des Netzwerks an die Container.
Die docker-compose.yml
für den oben beschriebenen Usecase sieht wie folgt aus:
version: "3.9"
services:
db:
image: mysql:5.7
container_name: db
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: dbpasswd
MYSQL_DATABASE: db
MYSQL_USER: db
MYSQL_PASSWORD: db
proxy:
image: nginx:latest
container_name: proxy
restart: always
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./nginx/error.log:/etc/nginx/error_log.log
- ./nginx/cache/:/etc/nginx/cache
- ./ssl/:/etc/letsencrypt/
ports:
- 80:80
- 443:443
app:
depends_on:
- db
- proxy
image: registry/myapp
restart: always
environment:
DBL_USER: db
DB_PASSWORD: db
DB_HOST: db
container_name: app
ports:
- 3000:3000
volumes:
db_data: {}
Die Nginx Konfiguration muss noch entsprechend als Reverse Proxy auf den
app
Container angepasst werden.
Docker Volumes
Docker Volumes bieten die Möglichkeit, anfallende persistente Daten in einem Container zu speichern. Volumes werden komplett durch Docker verwaltet und sind damit der offiziell empfohlene weg persistente Daten abzuspeichern.
- Anzeigen bestehender Volumes
C:\Users\Markus>docker volume ls DRIVER VOLUME NAME local 256895275dee26176790078f8470e124671e3f74abf7fb5f84e36aaa8f8e6a78 local c3687c2c12df99cfcbb6b725d57facf0e678ae776fdd6009009b7571ca1968cb local telly.config.toml local vscode
- Anlegen eines neuen Volumes
docker volume create data
Docker bietet auch die Möglichkeit, andere Storage Driver anzusprechen. Somit ist es möglich, die Volumes auf anderen Storage Medien zu speichern. Von Haus aus unterstützt Docker die folgenden Storage Drivers:
Docker Networking
Um die Container untereinander zu vernetzen, bietet Docker die Möglichkeit, über Bridges auf dem Hostsystem Container miteinander zu verbinden.
- Auflisten aller Netzwerke auf dem Host
C:\Users\Markus>docker network ls NETWORK ID NAME DRIVER SCOPE fa8c5ca426e1 bridge bridge local f9f00956c91d host host local 679b81f531b8 none null local
- Anlegen eines neues Netzwerks
docker network create --driver bridge new-network
Mit dem Parameter
--driver | -d
kann der Netzwerk Driver angegeben werden. - Konfiguration der Standard Bridge auslesen
C:\Users\Markus>docker network inspect bridge [ { "Name": "bridge", "Id": "fa8c5ca426e18372730c1dce298ddf97862c8574cf2e71e58ed9f5a584948158", "Created": "2022-01-12T14:58:18.607125133Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
Bei einem durch Docker verwalteten Netzwerk erfolgt die IP-Adressvergabe eigenständig durch Docker. Ebenso wie eine DNS Namensvergabe jeder Name eines Containers ist im Docker Netzwerk per DNS auflösbar. Somit ist es möglich, Container nach ihrem Namen im Netzwerk aufzurufen.
Es existieren auch noch einige andere Netzwermodelle, diese können hier eingesehen werden.
Mit Docker Swarm, lassen sich mehrere Docker Dienste zu einem Verbund zusammenschalten und somit können die Container auch Hostübergreifend miteinander kommunizieren.
Übersicht Overlay Netzwerke: https://docs.docker.com/network/overlay/
Beispielkonfiguration: https://docs.docker.com/network/network-tutorial-overlay/
Container Orchestrierung
Mit Container Orchistration lassen sich die Container in Clustern organisieren. In diesem Modus wird ein Cluster aus mehreren Containern einer Anwendung erstellt. Dieses Cluster ist dank Hostübergreifenden Netzwerk und Speicher in der lage eine Hochverfügbare Clusterumgebung zu schaffen.
In dieser konstelation ist der einzelne Container nicht mehr von großer bedeutung, dieser kann durch die Beachtung der 12 Faktoren einer Cloud Anwendung. Im Laufenden betrieb ohne störungen zu verursachen ausgetauscht werden.
Ein kleiner Überklich über die wichtigesten Eigenschaften einer Cloud Nativen Anwendung.
- Die Anwendung selbst darf keinen Status im Arbeitsspeicher halten.
- Persistente Daten dürfen nicht im Container gespeichert werden.
- Die Konfguration der Anwendung erfolgt über Umgebungsvariablen oder zentralisiertem Konfigurationsmanagenemt.
- Persistente Daten werden nur in Datenbanken gespeichert.
- Container mit Persistenten Daten speichern diese in Volumes.
- Volumes werden nicht auf dem Pod gespeichert sondern auf zentralisierten Storage Systemen z.B. S3 oder Ceph
Somit lassen sich im Live Betrieb wartungen und aktualisierungen durchführen, die die Verfübgarkeit der Anwendung in keinster weise beeinträchtigen.
Vielmehr lassen sich in einem solchen Cluster auch ganze Update oder Change Prozesse einbinden. Durch die eingebaute Versionierung in die Container Images ist es möglich. Das Cluster in Production, Staging, Test und Development zu unterteilen und entsprechend den eingehenden Traffic an die gewünschten stellen zu Routen. Hierdurch lässt sich der Grundgedanke von continuous deployment sehr gut umsetzen.
Verbreitete Container Orchestration Tools:
- Kubernetes
- RedHad OpenShift
- Apache Mesos
- HashiCorp Nomad
- Docker Swarm