Docker-Image für Bitbucket
« | 12 Aug 2020 | »Unlängst habe ich meine Bedenken gegen Docker geäußert und seinen Einsatz als “Fix gegen schlechtes Distributions-Design” kritisiert.
Jetzt wollen wir aber mal einen wichtigen Vorteil dieser Lösung aufzeigen:
Build-Images für Linux
Vorgeschichte
Das Chaos der Linux Distributionen, in denen jeder Hersteller andere Tools und vor allem andere Versionen von Tools und Bibliotheken mixt, ist ja leider ein bekannter Zustand.
Man kann de-facto keine Binärdateien erzeugen, die auf allen Linux-Distributionen laufen, außer:
- Man kompiliert alles (also auch C/C++
Standardbibliotheken) in das Programm hinein und macht es unabhängig von
versionierten Bibliotheken.
(Also das was das GATE Projekt unter anderem erreichen möchte.) - Oder man liefert gar keine Binaries, sondern verbreitet nur Sourcecodes, die auf dem Zielsystem erst kompiliert werden müssen. (Was Linux-Puristen am liebsten tun, aber für Endanwender meist ein Alptraum ist)
- Oder man erstellt Binaries für jede erdenkliche Distribution und paketiert diese im dort üblichen Paketsystem.
Klarerweise würde ich mich für die erste Methode aussprechen. Doch nachdem leider viel zu wenige Entwickler die Vorteile von statischer Kompilierung zu schätzen wissen, bleibt einem im Beruf als Entwickler nur die 3. Option, weil die Weitergabe von Sourcecode an den Endanwender entweder generell verboten ist, oder die Zielpersonen mit Kompilier-Abenteuer meist überfordert sind.
Und genau hier kann Docker seine Stärken gegenüber VM ausspielen. Wir brauchen nämlich keine separaten Kernels oder andere Hardware, sondern nur unterschiedliche Varianten von User-Land Bibliotheken.
Wir brauchen pro Distribution eine Build-Umgebung…
Lösung: Ein Docker pro Distro
Nachdem der Build-Prozess unter Linux immer gleich abläuft (also Quellcodes
einspielen und dann cmake
und/oder
make
aufrufen), erstellt man einfach pro Distribution ein Docker-Image, in
dem die Build-Toolchain installiert ist und baut sein Projekt durch.
Die Binaries linken dann genau gegen die Version von Bibliotheken, die in der
Distro eben Standard (oder nachinstalliert) sind.
Man könnte durchaus sagen, dass man mit Docker quasi ein Cross-Compiling-Setup
aufsetzt … nur dass es eben innerhalb des Images nichts “cross” ist und
damit diverse fehleranfällige Vorkonfigurationen entfallen.
Die Images werden mit den Standardtools aktualisiert, also apt
bei
Debian und Ubuntu,
zypper
bei SuSE, yum
für CentOS
oder RedHat, apk
für
Alpine und vieles mehr.
Docker Image für Bitbucket
Auch der Build von GATE auf BitBucket profitiert von einem eigenen Image. Die bereitgestellten generischen mussten bisher bei jeder Ausführung erneut gepatcht werden, damit alle Quellcodes durchkompiliert werden konnten.
Aber mit einem Verweis in bitbucket-pipelines.yml
auf ein vorbereitetes
Docker-Image auf Docker Hub, entfällt dieser
Schritt.
- Man schreibt sich also ein
Dockerfile
mit allen notwendigenapt-get install
Anweisungen (oder was auch immer das eingesetzte Linux braucht). - Dann lässt dann im Verzeichnis von
Dockerfile
das Kommando
docker build -t MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG .
aus. Bei mir war das
docker build -t gatelinker/cpp-build-env:ubuntu18 .
- Am Ende wird per
docker push MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG
das Image auf DockerHub hochgeladen. - Nun kann
bitbucket-pipelines.yml
um folgende beiden YAML Einträge erweitert werden:
Und schon kann man sein Projekt auf dem eigenen Docker-Image laufen lassen.
Fazit
Viele meiner Kollegen schwören auf Docker für die Erstellung von Build-Systemen
oder für das automatische Ausführen von Tests.
Und damit haben sie Recht. Docker eignet sich für diese Zwecke wirklich gut,
in kurzer Zeit “ein neues Linux” aufzusetzen, ohne dass es ein vollständiges
Linux System sein muss.
Ich bleibe zwar weiter bei meiner Meinung, dass Docker viel zu oft als billiger Patch für andere Probleme genutzt wird, kann aber den Wert der Software in anderen Bereichen nicht ignorieren.
Von daher werde ich in Zukunft auch mehr Build-Vorgänge nur noch in Docker Containern durchführen und nicht jedes Mal eine neue VM aufsetzen.