docker
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| docker [2020-11-13 19:37:38] – [ETCD starten] manfred | docker [2025-07-18 00:42:16] (aktuell) – [IPv6] david | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== Docker ====== | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | |||
| + | ===== Sonstiges ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | > docker volume rm $(docker volume ls -qf dangling=true) | ||
| + | |||
| + | > docker system prune -a -f | ||
| + | > docker volume prune -f | ||
| + | |||
| + | //für zukünftige Projekte __nur__ '' | ||
| + | |||
| + | |||
| + | ===== Docker in Verbindung mit einer Container-Orchestrierung ===== | ||
| + | |||
| + | [[Container-Orchestrierung]] | ||
| + | |||
| + | |||
| + | ===== Docker ist mehr als LXC ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | Ist Docker also nur ein Kommandozeilenprogramm zum Verwalten einer Containertechnologie, | ||
| + | * Die Ausführungsumgebung für Container im Linux-Kernel ist eine wichtige Grundlage, jedoch für die tägliche Arbeit als Softwareentwickler nicht einfach genug verwendbar. Docker bietet ein portables Format zum Zusammenstellen und Übertragen (packaging) von Containern mit einem entsprechenden API, das ein bequemes Arbeiten mit Containern ermöglicht. | ||
| + | * Docker hat einen De-facto-Standard für ein API für Anwendungscontainer geschaffen. Das hat den Vorteil, dass Tools unabhängig von der jeweiligen Containerimplementierung darauf aufsetzen können. Rund um Docker ist dadurch bereits ein reiches Ökosystem von Werkzeugen (z. B. Web-UI für Docker, Cluster-Management-Tools etc.) entstanden. | ||
| + | * Docker enthält eine eigene Sprache (Dockerfile) zum Erstellen von Containern beziehungsweise den zugrunde liegenden Images über Quellcode. Mit einem Dockerfile lässt sich ein Container-Image immer wieder ohne manuelle Installations- oder Konfigurationsschritte neu erstellen. | ||
| + | * Docker enthält eine Versionsverwaltung für Container-Images. | ||
| + | * Container-Images können auf anderen Images basieren. Man kann also einen Basiscontainer für beispielsweise ASP.NET vNext erstellen und diesen als Grundlage für viele verschiedene Anwendungen verwenden. | ||
| + | * Mit dem Docker Hub steht eine Plattform zum Teilen von Container-Images und Dockerfiles zur Verfügung. Hersteller wie Microsoft können dort offizielle Basis-Images anbieten (z. B. für ASP.NET vNext unter Ubuntu), und Sie können darauf aufbauen. Sie können aber auch Docker-Images für Ihre eigene Software dort anbieten, damit Ihre Kunden mit Docker Ihre Anwendung leichter installieren und betreiben können. | ||
| + | |||
| + | |||
| + | |||
| + | ===== Im Docker-Container Kommandos ausführen ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | docker exec -it -u root 7005b71222f6 free -h | ||
| + | |||
| + | docker exec -it -u root 7005b71222f6 mysql -uroot -pYWwzNHR6Cg -e "SHOW STATUS LIKE ' | ||
| + | |||
| + | echo "free -h" | sudo docker exec -i -u root 7005b71222f6 /bin/bash - | ||
| + | |||
| + | echo "mysql -uroot -pYWwzNHR6Cg -e 'SHOW STATUS LIKE \" | ||
| + | |||
| + | |||
| + | ===== Installation ===== | ||
| + | |||
| + | > apt install docker docker.io | ||
| + | |||
| + | [[https:// | ||
| + | > docker pull mysql | ||
| + | Using default tag: latest | ||
| + | latest: Pulling from library/ | ||
| + | 802b00ed6f79: | ||
| + | 30f19a05b898: | ||
| + | 3e43303be5e9: | ||
| + | 94b281824ae2: | ||
| + | 51eb397095b1: | ||
| + | 54567da6fdf0: | ||
| + | bc57ddb85cce: | ||
| + | d6cd3c7302aa: | ||
| + | d8263dad8dbb: | ||
| + | 780f2f86056d: | ||
| + | 8e0761cb58cd: | ||
| + | 7588cfc269e5: | ||
| + | Digest: sha256: | ||
| + | Status: Downloaded newer image for mysql: | ||
| + | | ||
| + | > docker image ls | ||
| + | REPOSITORY | ||
| + | mysql | ||
| + | |||
| + | jetzt können wir im Container eine BASH öffnen: | ||
| + | > docker container start -ai db01 | ||
| + | | ||
| + | oder | ||
| + | | ||
| + | > docker container run -it --name db00 mysql bash | ||
| + | root@3fe6bea75eeb:/# | ||
| + | root@3fe6bea75eeb:/# | ||
| + | root@3fe6bea75eeb:/# | ||
| + | root@3fe6bea75eeb:/# | ||
| + | |||
| + | den Container " | ||
| + | > docker container run -de MYSQL_ROOT_PASSWORD=geheim -p 3321:3306 --name db01 mysql | ||
| + | > docker container ls | ||
| + | CONTAINER ID IMAGE | ||
| + | 3fe6bea75eeb | ||
| + | |||
| + | wenn sie läuft, dann kann man so die Statistischen Werte des Containers sehen: | ||
| + | > docker container stats db01 | ||
| + | CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS | ||
| + | 3fe6bea75eeb | ||
| + | |||
| + | > docker container exec -it db01 bash | ||
| + | root@3fe6bea75eeb:/# | ||
| + | root@3fe6bea75eeb:/# | ||
| + | |||
| + | den Container anhalten | ||
| + | > docker container stop db01 | ||
| + | |||
| + | den Container löschen | ||
| + | > docker container rm db01 | ||
| + | |||
| + | einen neuen Container anlegen und starten, der auch per SSH erreichbar sein soll + SSH-Schlüssel hinterlegen + SSHD-Installation: | ||
| + | > docker container run -de MYSQL_ROOT_PASSWORD=geheim -p 3321:3306 -p 2221:22 --name db02 mysql | ||
| + | > docker container exec -it db02 bash -c "apt -y update ; apt -y install ssh vim screen ; mkdir /root/.ssh ; echo ' | ||
| + | > ssh -i .ssh/ | ||
| + | |||
| + | leider funktioniert das nur auf IPv6: | ||
| + | > netstat -antp | fgrep 21 | ||
| + | tcp6 | ||
| + | tcp6 | ||
| + | |||
| + | [[https:// | ||
| + | > sysctl net.ipv6.bindv6only | ||
| + | |||
| + | |||
| + | ===== IPv6 ===== | ||
| + | |||
| + | docker hat ein default bridge netzwerk welches sich zwecks abwärtskompatibilität anders verhält als selbst erstellte bridge netzwerke, daher ist es empfehlenswert eigene bridge netzwerke zu erstellen: | ||
| + | |||
| + | > docker network create bridge64 --ipv6 | ||
| + | > docker network create bridge6 --ipv6 --ipv4=false | ||
| + | > docker network create bridge4 | ||
| + | |||
| + | man kann auch angeben auf welcher adresse ports standardmäßig exposed/ | ||
| + | |||
| + | > docker network create bridge64 --ipv6 -o com.docker.network.bridge.host_binding_ipv4="::" | ||
| + | > docker network create bridge64 --ipv6 -o com.docker.network.bridge.host_binding_ipv4=" | ||
| + | > docker network create bridge64 --ipv6 -o com.docker.network.bridge.host_binding_ipv4=":: | ||
| + | > docker network create bridge64 --ipv6 -o com.docker.network.bridge.host_binding_ipv4=" | ||
| + | |||
| + | dadurch verhält sich die minimale port notation (nur port ohne ip) so als ob man die jeweils konfigurierte ip mit angegeben hätte (die beiden letzteren sind äußerst praktisch, wenn die services nur auf localhost erreichbar sein sollen): | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | wichtig zu wissen ist, dass ipv6-only services im container standardmäßig nicht erreichbar sind, egal welchen oben gezeigten weg man wählt, denn docker macht auch in ipv6 aktivierten netzwerken immer ipv6 -> ipv4 und/oder ipv4 -> ipv4 nat (applikationen im container müssen also den socket auf dem sie listen wollen mit dem flag IPV6_V6ONLY gleich false oder 0 erstellen, in nginx geht das bspw. mit ipv6only=off), | ||
| + | |||
| + | |||
| + | ===== einen Docker-Container auf einer dedizierten IP per TAP laufen lassen ===== | ||
| + | |||
| + | Testumgebung: | ||
| + | * //Name des Docker-Containers:// | ||
| + | * //IP des Hostsystems:// | ||
| + | * //IP für des Docker-Container:// | ||
| + | * // | ||
| + | * // | ||
| + | * // | ||
| + | * // | ||
| + | * // | ||
| + | * //hier werden unsere frischen Docker-Images gebaut:// '' | ||
| + | * //dieses Docker-Image verwenden wir:// '' | ||
| + | |||
| + | |||
| + | ==== den Docker-Container mit dedizierter IP starten ==== | ||
| + | |||
| + | ip tuntap add mode tap name tap21 | ||
| + | ip a add 10.10.1.21/ | ||
| + | brctl addif br0 tap21 | ||
| + | docker run -dit --restart=always --name test01 --add-host test01: | ||
| + | |||
| + | |||
| + | ==== den Docker-Container mit dedizierter IP stoppen ==== | ||
| + | |||
| + | docker container stop test01 | ||
| + | docker container rm test01 | ||
| + | brctl delif br0 tap21 | ||
| + | ip a del 10.10.1.21/ | ||
| + | ip tuntap del mode tap name tap21 | ||
| + | |||
| + | |||
| + | ===== einen Docker-Container auf einer dedizierten IP per Bridge laufen lassen ===== | ||
| + | |||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | docker run -itd ubuntu: | ||
| + | apt-get update | ||
| + | apt-get install net-tools | ||
| + | docker run --network=newnet -itd ubuntu | ||
| + | docker network create --driver=bridge --subnet=172.28.0.0/ | ||
| + | docker run -itd --network=newnet -p 80:80 http | ||
| + | |||
| + | |||
| + | ===== Docker-Swarm ===== | ||
| + | |||
| + | [[Docker-Swarm]] | ||
| + | |||
| + | |||
| + | ===== über ETCD ===== | ||
| + | |||
| + | |||
| + | ==== ETCD starten ==== | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | root@host01: | ||
| + | root@host01: | ||
| + | |||
| + | <file etcd.sh> | ||
| + | docker network create --driver overlay dbnetz3306 | ||
| + | |||
| + | #docker service update --network-add dbnetz3306 etcd | ||
| + | |||
| + | docker service create --name etcd --replicas 3 \ | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | |||
| + | # cd / | ||
| + | # bash etcd.sh | ||
| + | pf7s765wzpjpc18jtsfhh6iz1 | ||
| + | 8dxyua2t5izyz4plnq58447gw | ||
| + | llkrwh0l9ktpiix2ci91usgyw | ||
| + | li48rs2rlh0wlme7ul38q3a0u | ||
| + | overall progress: 3 out of 3 tasks | ||
| + | 1/3: running | ||
| + | 2/3: running | ||
| + | 3/3: running | ||
| + | verify: Service converged | ||
| + | |||
| + | |||
| + | # docker service ls | ||
| + | ID NAME MODE REPLICAS | ||
| + | li48rs2rlh0w | ||
| + | t8laa0ewj5rj | ||
| + | |||
| + | # curl -v GET https:// | ||
| + | |||
| + | |||
| + | === jp === | ||
| + | |||
| + | <file text jp --help> | ||
| + | jq - commandline JSON processor [version 1.6] | ||
| + | |||
| + | Usage: | ||
| + | jq [options] --args <jq filter> [strings...] | ||
| + | jq [options] --jsonargs <jq filter> [JSON_TEXTS...] | ||
| + | |||
| + | jq is a tool for processing JSON inputs, applying the given filter to | ||
| + | its JSON text inputs and producing the filter' | ||
| + | standard output. | ||
| + | |||
| + | The simplest filter is ., which copies jq's input to its output | ||
| + | unmodified (except for formatting, but note that IEEE754 is used | ||
| + | for number representation internally, with all that that implies). | ||
| + | |||
| + | For more advanced filters see the jq(1) manpage ("man jq") | ||
| + | and/or https:// | ||
| + | |||
| + | Example: | ||
| + | |||
| + | $ echo ' | ||
| + | { | ||
| + | " | ||
| + | } | ||
| + | |||
| + | Some of the options include: | ||
| + | -c | ||
| + | -n use `null` as the single input value; | ||
| + | -e set the exit status code based on the output; | ||
| + | -s read (slurp) all inputs into an array; apply filter to it; | ||
| + | -r | ||
| + | -R read raw strings, not JSON texts; | ||
| + | -C | ||
| + | -M | ||
| + | -S sort keys of objects on output; | ||
| + | --tab use tabs for indentation; | ||
| + | --arg a v set variable $a to value <v>; | ||
| + | --argjson a v set variable $a to JSON value <v>; | ||
| + | --slurpfile a f set variable $a to an array of JSON texts read from <f>; | ||
| + | --rawfile a f set variable $a to a string consisting of the contents of <f>; | ||
| + | --args | ||
| + | --jsonargs | ||
| + | -- | ||
| + | |||
| + | Named arguments are also available as $ARGS.named[], | ||
| + | positional arguments are available as $ARGS.positional[]. | ||
| + | |||
| + | See the manpage for more options. | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== ETCD benutzen ==== | ||
| + | |||
| + | in einen Docker-Container ('' | ||
| + | root@host01: | ||
| + | |||
| + | alle IPs ausgeben | ||
| + | # hostname -I | ||
| + | 10.0.0.230 172.18.0.10 10.33.06.42 | ||
| + | |||
| + | die IP-Adresse aus dem Hostnamen ermitteln (geht nur wenn DNS funktioniert) | ||
| + | # hostname -i | ||
| + | 10.33.06.42 | ||
| + | |||
| + | nachschauen, | ||
| + | wenn nicht, dann davor hinschreiben | ||
| + | if [ " | ||
| + | DISCOVERY_SERVICE=" | ||
| + | fi | ||
| + | |||
| + | die eigene IP in den ETCD eintragen (ist nur für 60 Sekunden gültig) | ||
| + | # curl " | ||
| + | |||
| + | kontrollieren, | ||
| + | # curl " | ||
| + | % Total % Received % Xferd Average Speed | ||
| + | | ||
| + | 100 | ||
| + | 10.33.06.42 | ||
| + | |||
| + | nach 60 Sekunden ist der Eintrag wieder raus: | ||
| + | # curl " | ||
| + | % Total % Received % Xferd Average Speed | ||
| + | | ||
| + | 100 | ||
| + | |||
| + | |||
| + | === ETCD-Beispielaktionen === | ||
| + | |||
| + | den Wert " | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | {" | ||
| + | |||
| + | den Wert auslesen: | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | 9999 | ||
| + | |||
| + | den Schlüssel auslesen: | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | / | ||
| + | |||
| + | den Schlüssel mit Wert löschen: | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | {" | ||
| + | |||
| + | jetzt sind Schlüssel und Wert raus: | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | |||
| + | das Verzeichnis mit allen Schlüsseln samt Werten löschen: | ||
| + | [root@eceae28581e6 ~]# curl http:// | ||
| + | |||
| + | |||
| + | ===== Container-Orchestrierung ===== | ||
| + | |||
| + | |||
| + | ==== Beziehung zwischen Kubernetes und Docker ==== | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | Kubernetes wird am häufigsten zusammen mit von Docker verwalteten Containern verwendet. | ||
| + | Doch ist es nicht strikt davon abhängig. | ||
| + | Wie also funktionieren beide zusammen? | ||
| + | Dies wird in diesem ausführlichen Kubernetes-Guide erläutert. | ||
| + | Hierfür kommt zudem Payara Micro zum Einsatz, eine leichtgewichtige Open-Source-Plattform, | ||
| + | |||
| + | Kubernetes definiert ein Container Runtime Interface (CRI), das Container-Plattformen implementieren müssen, um kompatibel zu sein. | ||
| + | Diese Implementierungen werden umgangssprachlich als „Shims“ bezeichnet. | ||
| + | Das macht die Kubernetes-Plattform unabhängig, | ||
| + | Die automatische Skalierung sowie die Failover-Sicherung sind nur zwei der Vorteile moderner Cloud-Plattformen, | ||
| + | Allerdings gibt es immer noch Schwierigkeiten mit dieser Architektur, | ||
| + | - Das Starten und Stoppen einer Instanz ist langsam. | ||
| + | - Die Kommunikation zwischen den Nodes in dieser Architektur kann sehr komplex sein. | ||
| + | |||
| + | Kubernetes ist eine Plattform für die Verwaltung von containerisierten Services. Dabei handelt es sich um ein Tool, mit dem Details wie z. B. das Separieren von Nodes abstrahiert werden können, während andere Dinge, wie Rolling Upgrades, Failover und Services automatisiert werden. Die Idee ist, auf ähnliche Weise deployen zu können, egal ob man dies lokal oder in der Cloud tun möchte. | ||
| + | |||
| + | ...folgenden Tools müssen für dieses Beispiel bereits installiert und konfiguriert sein: | ||
| + | * Maven (v3+) | ||
| + | * JDK 8 | ||
| + | * Docker | ||
| + | |||
| + | Kubernetes ist für den Einsatz mit einem Cloud-Anbieter vorgesehen. Es gibt dennoch mehrere Möglichkeiten, | ||
| + | |||
| + | Verwendet man Linux, so sind __MicroK8s__ und __Minikube__ die zwei Wegbereiter. Letzteres läuft unter Windows, MacOS und Linux. Minikube führt einen Kubernetes-Cluster in einer einzelnen VM aus, wohin hingegen MicroK8s mit Snap installiert wird und lokal mit minimalem Overhead läuft. | ||
| + | |||
| + | MicroK8s wurde vom Kubernetes-Team Canonical entwickelt, deshalb muss es mit dem Canonical-Linux-Packetmanager (snapd) installiert werden. | ||
| + | - Canonical-Linux-Packetmanager installieren: | ||
| + | - MicroK8s installieren: | ||
| + | - Kubernetes-Main-Utility umbenennen (//um '' | ||
| + | - das umbenennen rückgängig machen: '' | ||
| + | |||
| + | Einige wichtige Befehle, die nur von MicroK8s zur Verfügung gestellt werden: | ||
| + | * Starts MicroK8s and allows provisioning nodes: '' | ||
| + | * Stops MicroK8s: '' | ||
| + | * Clear all resources and revert kubernetes to a ' | ||
| + | |||
| + | Wir müssen sicherstellen, | ||
| + | |||
| + | prüfen, ob MicroK8s richtig installiert wurde: | ||
| + | > kubectl get all | ||
| + | |||
| + | |||
| + | Fatzit: | ||
| + | **// | ||
| + | |||
| + | |||
| + | ==== Kubernetes oder Docker Swarm? ==== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | Wer vor der Aufgabe steht, mehrere containerisierte Services in einem Cluster zu verwalten, kommt an einer Lösung zur Container-Orchestrierung kaum vorbei. Etabliert haben sich in den letzten Monaten hier vor allem Kubernetes und Docker Swarm. Im Interview mit JAXenter erklärt Jörg Müller, Principal Consultant bei innoQ und Sprecher auf dem Microservices Summit, welches Tool für welchen Einsatzzweck geeignet ist. | ||
| + | |||
| + | Kubernetes konkurriert als Orchestrierungslösung u.a. mit Docker Swarm. Wo liegen hier die Unterschiede: | ||
| + | |||
| + | |||
| + | Fatzit: | ||
| + | **// | ||
| + | * Beide lösen das Problem der Container-Orchestrierung gut, benutzen dabei aber unterschiedliche Philosophien. | ||
| + | * __Docker Swarm setzt auf eine einfache Installation und einen eher monolithischen Ansatz.__ Alles Notwendige ist in einem Binary enthalten und kann damit leicht auf mehrere Nodes verteilt werden. Auch die Konfiguration folgt diesem Prinzip der einfachen Nutzung. Sie ist in vielen Fällen nicht komplizierter als die Konfiguration mehrerer Container mit Docker-Compose, | ||
| + | * __Kubernetes verfolgt einen kleinteiligen Ansatz.__ Es besteht aus vielen Komponenten, | ||
| + | * Ähnlich ist es mit der Konfiguration. Diese ist bei Kubernetes deutlich umfangreicher. Aber auch hier gibt es viel Unterstützung durch Werkzeuge. __Die Einstiegshürde ist bei Kubernetes sicher höher als bei Docker Swarm.__ Letztendlich werden die eigenen Anforderungen an die Anpassungsfähigkeit des Clusters ausschlaggebend für die Entscheidung für die eine oder andere Lösung sein. | ||
| + | * __Momentan muss man bei der Installation eines Kubernetes Clusters sehr darauf achten, dass die notwendigen Security-Funktionen installiert und eingerichtet werden.__ Dabei geht es um Beschränkungen der Möglichkeiten in einzelnen Containern oder Pods, um umfangreiche Einstellungsmöglichkeiten für Nutzerrechte und um Firewall-Regeln innerhalb des Clusters. Inzwischen bieten viele der Installationstools dafür bereits Lösungen, aber oft ist das noch mit Mehraufwand verbunden. | ||
| + | |||
