6 Punkte von GN⁺ 2024-11-24 | 1 Kommentare | Auf WhatsApp teilen
  • Bocker ist ein Projekt, das Docker in rund 100 Zeilen Bash implementiert und einen Docker-ähnlichen Ablauf für Image-Pull, Container-Run, Log-Anzeige, Commit und Löschen bietet
  • Für die Ausführung werden btrfs-progs, curl, iproute2, iptables, libcgroup-tools, util-linux 2.25.2 oder neuer sowie coreutils 7.5 oder neuer benötigt; außerdem sind ein btrfs-Dateisystem unter /var/bocker und eine bridge0-Netzwerkkonfiguration erforderlich
  • Das README-Beispiel zeigt den Ablauf, bei dem ein centos:7-Image gepullt wird, anschließend Befehle in einem Container ausgeführt werden und das Ergebnis von yum install -y wget per commit gespeichert wird, sodass bei späteren Ausführungen /usr/bin/wget vorhanden ist
  • Bocker läuft als root und ändert Netzwerkschnittstellen, Routing-Tabellen und Firewall-Regeln; daher wird empfohlen, es in einer virtuellen Maschine auszuführen. Es gibt keine Garantie gegen mögliche Systemschäden
  • Derzeit sind docker pull, images, ps, run, exec, logs, commit, rm/rmi, Networking sowie CGroups-basierte Quotas implementiert; Data Volumes, Data-Volume-Container und Port Forwarding sind noch nicht implementiert

Zweck und Umfang von Bocker

  • Bocker ist ein Projekt, das Docker in rund 100 Zeilen Bash implementiert
  • Das README zeigt Docker-ähnliche Befehlsabläufe auf Bash-Basis und umfasst Funktionen wie Image-Verwaltung, Container-Ausführung, Log-Abfrage, Commit von Änderungen und Ressourcenlimits

Laufzeitvoraussetzungen

  • Für die Ausführung werden folgende Pakete benötigt
    • btrfs-progs

      • curl
      • iproute2
      • iptables
      • libcgroup-tools
      • util-linux 2.25.2 oder neuer
      • coreutils 7.5 oder neuer
      • Da die meisten Distributionen kein ausreichend aktuelles util-linux enthalten, ist es wahrscheinlich nötig, die util-linux-2.25-Quellen herunterzuladen und selbst zu kompilieren
      • Das System benötigt folgende Konfiguration
      • ein unter /var/bocker gemountetes btrfs-Dateisystem
      • eine Netzwerk-Bridge namens bridge0 mit der IP 10.0.0.1/24
      • aktiviertes IP-Forwarding unter /proc/sys/net/ipv4/ip_forward
      • Firewall-Einstellungen, die Traffic von bridge0 an die physische Schnittstelle routen
      • Eine Vagrantfile ist enthalten, um die benötigte Umgebung leichter erstellen zu können

Hinweise zur Ausführung

  • Auch wenn die Voraussetzungen erfüllt sind, wird empfohlen, Bocker in einer virtuellen Maschine auszuführen
  • Bocker läuft als root und muss folgende Elemente ändern
    • Netzwerkschnittstellen
    • Routing-Tabellen
    • Firewall-Regeln
  • Das README weist ausdrücklich darauf hin, dass nicht garantiert werden kann, dass Bocker das System nicht beschädigt

Beispielhafter Nutzungsablauf

  • Wenn mit bocker pull centos 7 das Image centos:7 geholt wird, entsteht eine Image-ID wie img_42150
  • bocker images zeigt Image-ID und Quelle an
    • Beispielausgabe: img_42150, centos:7
  • bocker run img_42150 cat /etc/centos-release gibt die CentOS-Release-Informationen im Container aus
    • Beispielausgabe: CentOS Linux release 7.1.1503 (Core)
  • bocker ps zeigt die ID und den Befehl des ausgeführten Containers an
  • bocker logs ps_42045 zeigt die Ausgabelogs dieses Containers an
  • bocker rm ps_42045 entfernt den Container
  • Bei der ersten Ausführung von bocker run img_42150 which wget ergibt sich, dass wget nicht vorhanden ist
  • Nachdem wget mit bocker run img_42150 yum install -y wget installiert wurde, werden die Änderungen mit bocker commit ps_42018 img_42150 in das Image übernommen
  • Danach gibt bocker run img_42150 which wget /usr/bin/wget aus

Ressourcenlimits und CGroups

  • Das Bocker-Ausführungsbeispiel zeigt, dass Container unter CGroups abgelegt werden
    • In /proc/1/cgroup erscheinen Einträge wie memory:/ps_42152 und cpuacct,cpu:/ps_42152
  • Beispiele für die standardmäßigen CPU-Shares und Speicherlimits sind
    • /sys/fs/cgroup/cpu/ps_42152/cpu.shares: 512
    • /sys/fs/cgroup/memory/ps_42152/memory.limit_in_bytes: 512000000
  • Ressourcenlimits können über Umgebungsvariablen geändert werden
    • BOCKER_CPU_SHARE=1024
    • BOCKER_MEM_LIMIT=1024
  • Das Beispiel nach der Änderung zeigt folgende Werte
    • CPU-Shares: 1024
    • Speicherlimit: 1024000000

Implementierte und nicht implementierte Funktionen

  • Derzeit sind folgende Funktionen implementiert
    • docker build
    • docker pull
    • docker images
    • docker ps
    • docker run
    • docker exec
    • docker logs
    • docker commit
    • docker rm / docker rmi
    • Networking

      • Quota Support / CGroups
      • bocker init bietet eine sehr eingeschränkte Implementierung von docker build
      • Folgende Funktionen sind noch nicht implementiert
      • Data Volume Containers
      • Data Volumes
      • Port Forwarding

Lizenz

  • Bocker ist freie Software, die unter den Bedingungen der GNU General Public License weiterverbreitet und verändert werden darf
  • Als Lizenzversion kann GPL v3 oder eine spätere von der Free Software Foundation veröffentlichte Version gewählt werden
  • Das Programm wird in der Hoffnung verbreitet, nützlich zu sein, jedoch ohne implizite Gewährleistung der Marktgängigkeit oder Eignung für einen bestimmten Zweck

1 Kommentare

 
GN⁺ 2024-11-24
Meinungen auf Hacker News
  • Ich habe einmal etwas Ähnliches mit proot gebaut, es hieß Bag [1], und ich hätte es wohl nicht als Docker-Alternative beschrieben.
    Mit cgroups hatte es nichts zu tun, und auch das Command-Line-Interface war anders als bei Docker. Der Hintergrund war, dass ich zur Umgehung von Internetzensur und Deep Packet Inspection eine Proxy-Kette gebaut hatte, die wie normaler HTML-Traffic aussehen sollte. Sie musste überall weiterlaufen, aber ich wollte sie nicht als native Android-App portieren.
    Ich wollte sie in Termux laufen lassen, aber damals gab es in Termux kein JDK/JRE; wenn man mit proot eine Arch-Linux-Umgebung startete, konnte man ein JDK nutzen. Die Arch-Umgebung innerhalb von Termux war insgesamt nützlicher, und es ließ sich per Skript leicht automatisieren, Wegwerf-Umgebungen mit unterschiedlichen Konfigurationen zu erstellen und zu löschen, anschließend per proot hineinzugehen und nur einen einzelnen Befehl auszuführen. Deshalb nannte ich es bag.sh, weil es etwas deutlich Kleineres als ein Frachtcontainer sein sollte.
    Interessanterweise enthält bag.sh auch noch eine Roadmap/TODO, die seit fünf Jahren nicht angefasst wurde. Da ich es auf einem mobilen Bildschirm geschrieben habe und es ohne Scrollen sehen wollte, ist das meiste auf 40 Spalten umbrochen.
    [1]: https://github.com/hkoosha/bag

    • Solche Geschichten dürfte es ziemlich viele gegeben haben. Ich musste einmal mehrere Komponenten in eine einzige Umgebung paketieren, weil eine VM nicht passte, und habe dafür chroot und deb-bootstrap verwendet und mit makeself einen Installer gebaut.
      Ich baute ein kleines Debian unter /opt, das die benötigte Software und Abhängigkeiten wie MySQL enthielt. Es funktionierte ziemlich gut und wurde genutzt, bis das Unternehmen, für das ich es gebaut hatte, etwa 2016 übernommen wurde. Allgemeiner gesagt halte ich es für eine der besten Methoden, die interne Funktionsweise zu lernen, wenn man eine grobe Version einer großen Anwendung selbst implementiert.
    • Im Skript scheinen ein paar wichtige Anführungszeichen zu fehlen. Es wäre gut, shellcheck darüber laufen zu lassen.
      mkdir -p $(dirname "$2")
    • Auf einem 8-Zoll-Tablet im Querformat bekam ich gerade so etwa 80x22 in tatsächlich lesbarer Größe hin.
      In Kombination mit einer etwa 10 Zoll großen Bluetooth-Tastatur, die bequem in die Innentasche einer Lederjacke passt, kann man ohne Tasche das Haus verlassen und in der Ecke eines nahegelegenen Biergartens Code schreiben. Überraschenderweise ist man dabei sogar produktiv; vielleicht weil der Wechsel zu den üblichen Ablenkungen etwas mehr Reibung verursacht als am Laptop, sodass man eher einen Schluck Bier nimmt und weiter auf den Code starrt.
  • Ich mag solche Dinge. Ich mochte schon immer Sachen, die mit minimalem Bash gebaut sind.
    Es gibt auch einen Proof of Concept für einen internen Cluster-Load-Balancer in 40 Zeilen Bash, den ich vor etwa 10 Jahren bei einem Hackathon gebaut habe, den ich organisiert hatte, um verteilte Infrastruktur wie Docker und Mesos bekannter zu machen: https://github.com/cell-os/metal-cell/blob/master/discovery/...
    Wahrscheinlich ist es verloren gegangen, aber es gab auch ein redundantes und verteiltes Colo-to-Cloud-Übertragungstool auf Basis von Reverse-SSH-Tunneln. Auf Shell Fu und ähnlichen Seiten sind solche Sammlungen gut zusammengestellt: https://www.shell-fu.org/

    • shell-fu.org ist großartig, aber ich würde auch gern die Kommentare anderer Nutzer sehen.
  • Dass sich ein großer Teil von Docker so einfach neu implementieren lässt, ist das größte Problem, vor dem Docker als Unternehmen stand und immer noch steht. Im Kern ist es nämlich eher Glue Code, der Kernel-Funktionen miteinander verbindet.
    Wo Docker tatsächlich Mehrwert schafft, ist nicht nur Docker Hub, sondern Docker for Windows und Mac. Die integrierte Erfahrung ist deutlich besser, als selbst mit VirtualBox und Vagrant herumzuhantieren, um Docker auf einer Entwicklungsmaschine laufen zu lassen.

    • Rancher Desktop ist ebenfalls eine praktikable Option und kostenlos. Nach der neuen Docker-Lizenz sind viele, darunter auch mein Arbeitsplatz, dorthin gewechselt.
      Persönlich denke ich, dass die eigentliche Magie von Docker das Docker/OCI-Image-Format war. Es löst Caching und die Verteilung von Container-Images hervorragend, und genau das ist weiterhin der Kern dessen, was es von „vollständigen“ VMs und deren Workflows unterscheidet.
    • Docker Desktop auf dem Mac ist ein eingeschränktes, unterprivilegiertes Durcheinander. Docker CLI mit Colima auf dem Mac hat zwar ebenfalls Rechtebeschränkungen, aber immerhin kann man die absurde Lizenz und die Docker-GUI vermeiden.
      Unter Windows kann man Docker in WSL verwenden, und das funktioniert sehr gut. Ich kann schwer nachvollziehen, warum man Docker Desktop nutzt.
    • Unter macOS verwende ich einfach Colima; die Erfahrung ist viel besser und es ist deutlich leichtergewichtig.
    • Nein, Docker hätte zuerst eine PaaS wie CloudRun, Render oder Fly bauen und sie teuer an Unternehmen verkaufen sollen.
      Stattdessen bauten sie das unausgereifte Docker Swarm, das nicht zuverlässig funktionierte, und wurden schnell von Kubernetes verdrängt.
    • Unter beliebten und profitablen Systemen gibt es viele, die man „leicht“ neu implementieren kann. Ich dachte, der Wert von Docker liege in Docker-Images, und ich vermute, so wird Docker auch genutzt.
      Meine eigene Nutzung bestand nur darin, vor ein paar Jahren die virtuelle Build-Umgebung von jemand anderem zu holen, um Software zu bauen.
  • Im Repository stehen Formulierungen wie „noch nicht implementiert“, „TODO“ und „in Arbeit“, und wenn man sieht, dass der letzte Commit Jahre zurückliegt, ist das irgendwie gut.
    Dadurch fühle ich mich etwas besser dabei, nicht zu den TODOs zurückzukehren, die ich in meinem eigenen Code verstreut habe. Das soll den Autor nicht herabsetzen, es ist einfach beruhigend.

    • Guter Punkt. Das ist überhaupt keine Herabsetzung, sondern eher ein Normalisieren dieses Zustands, und das gefällt mir.
      Wenn man bei unbezahltem, freiwilligem Hobby-Code nur deshalb eine Verpflichtung verspürt, weil er öffentlich ist, macht Coding weniger Spaß, und man veröffentlicht am Ende vielleicht Code nicht, den man sonst veröffentlicht hätte.
    • Die meisten Projekte, vielleicht sogar alle Projekte, werden nie fertig, denke ich. Wichtig ist, zu wissen, wann man aufhören sollte.
    • Finde ich gut. Etwas kann einfach fertig sein, und man muss nicht immer haufenweise nächste Ideen haben, auch wenn es meistens immer noch eine nächste Idee gibt.
      Wenn es immer eine nächste Idee gibt, bleiben per Definition auch immer unerledigte TODOs übrig. Eigentlich sollte das der Normalzustand aller Projekte sein.
    • Wenn man ein Projekt startet, sollte man Zeit darauf verwenden, über „Nicht-Ziele“ nachzudenken, also über Features, die einem zwar einfallen, die man aber bewusst nicht implementieren will.
      Klare Grenzen für den Scope zu setzen, ist völlig in Ordnung und oft hilfreich. So vermeidet man, dass sich das Projekt ewig „unfertig“ anfühlt, weil man ständig Nebenpfaden folgt.
    • Völlig in Ordnung. Wenn ein Programm das tut, was ich will, und meine Arbeit erledigt ist, höre ich mit der Entwicklung auf. Software ist nicht mein Hobby.
  • Es überrascht mich, dass lazydocker noch nicht als hervorragende Alternative zu Docker Desktop erwähnt wurde. Läuft unter Linux/macOS/Windows [1]
    Es ist eine recht funktionsreiche Terminal-UI und hat außerdem den Vorteil, dass man es über SSH ausführen kann.
    [1] https://github.com/jesseduffield/lazydocker

    • Wurde buchstäblich erst vor ein paar Tagen gepostet: https://news.ycombinator.com/item?id=42214873
    • Lazydocker sieht definitiv interessant aus, aber eine Eigenwerbungsanzeige für ein Produkt aus einem völlig anderen Bereich in der README.md eines Open-Source-Projekts ist schon ziemlich heftig.
      Zumindest habe ich so etwas zum ersten Mal gesehen. Ich frage mich auch, ob solche Werbung nach den Nutzungsbedingungen oder der Acceptable-Use-Policy von GitHub erlaubt ist.
  • Ich frage mich, warum Bocker so oft auf der Startseite landet. Ist Docker 2024 immer noch so kontrovers?
    Ich verstehe nicht, warum man nicht anerkennt, dass Docker tatsächlich nützliche Dinge gebracht hat, vor allem Softwareverteilung und „einfach überall ausführen“.

    • Das ist lediglich ein Lernwerkzeug, um zu sehen, wie Docker funktioniert.
      Docker ist eine Kombination bereits vorhandener Kernel-Technologien: Namespaces, cgroups, Union-Dateisysteme und wahrscheinlich noch ein paar Dinge mehr.
    • Es landet deshalb oft auf der Startseite, weil viele Leute Docker für etwas enorm Komplexes halten, es auf der grundlegendsten Ebene aber tatsächlich ziemlich elegant und verständlich ist.
      Das macht es interessant, und es ist im Grunde die perfekte HN-Geschichte.
    • Es landet vielleicht nicht auf der Startseite, um Docker schlechtzumachen, sondern weil Leute sehen, dass Docker nützlich ist, und wissen wollen, wie es funktioniert. Bocker kann ein Einstieg in diese Technologien sein.
    • Ich habe in der Firma overlayfs gezeigt, um einen langen CI-Prozess zu verkürzen, und alle waren vom Geschwindigkeitsgewinn überrascht.
      Erst nachdem ich es ein paar Leuten vorgeführt hatte, wurde mir klar, dass sie auch einfach / hätten verwenden können – oder dass ich ihnen genauso gut Docker hätte geben können.
  • Als eine Art Bruder von einer anderen Mutter gibt es https://bastillebsd.org/
    Bastille verwendet viele Strukturen, wie man sie von Docker erwarten würde, in Shell, um FreeBSD-Jails zu verwalten. Es hat sehr wenige Abhängigkeiten, weshalb ich es lieber mag als andere Jail-Management-Software für BSD.

    • cbsd ist auch ziemlich beeindruckend: shttps://www.bsdstore.ru/en/about.html
      Allerdings ist es trotz CLI/TUI-basierter Werkzeuge eher eine Lösung nahe am „maximalen Overkill“. Zurzeit gehe ich die Schritte durch, Jails nur mit der FreeBSD-Basiskonfiguration zu erstellen und zu verwalten, aber das ist nur eine Übergangsphase.
      Ich mache das nur so lange, bis sich das Zusammenspiel ausreichend in meinem Kopf festgesetzt hat und ich beim Debugging sicher bin; danach werde ich wie ein vernünftiger Mensch aufhören, Steine aneinanderzuschlagen, und zu höherwertigen Tools zurückkehren.
    • Genau. Für ein Shell-Skript mit etwa 100 Zeilen bringt es ziemlich viel Mehrwert.
      Allerdings hat es eine Weile gedauert, bis ich verstanden habe, warum es Bastille heißt. La Bastille war eine Festung, die während des Hundertjährigen Kriegs gebaut wurde, um Paris gegen englische Angriffe zu verteidigen, und später in ein Gefängnis umgewandelt wurde.
  • Bei der Stelle „Die meisten Distributionen stellen keine ausreichend aktuelle Version von util-linux bereit, daher wird man hier den Quellcode holen und selbst kompilieren müssen“ sollte man vorsichtig sein.
    Das standardmäßige Installationspräfix ist /usr/bin, daher kann der Installationsprozess den bestehenden mount-Befehl mit einer Version überschreiben, die nicht vorhandene Libraries verlangt. Dann mountet der Kernel beim nächsten Booten das Dateisystem schreibgeschützt.

    • Es sollte /usr/local/bin sein.
  • Für den Alltagsgebrauch nicht gut, aber es vermittelt ein Gefühl dafür, was Docker ist und wie es funktioniert.
    Unter Linux ist Docker im Grunde ein schickes chroot.

    • Unter macOS/Windows usw. ist Docker im Grunde ein schickes chroot in einer Linux-VM.
  • Fun Fact: Docker begann in Bash, wechselte später zu Python und landete schließlich bei Go.
    Außerdem schrieb jemand bei einem Docker-Meetup 2013 einen Docker-Klon in Bash. Leute wollen lernen, und es wäre schön, wenn solche Dinge dabei helfen.