Docker-Image für Bitbucket

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:

  1. 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.)
  2. 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)
  3. 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.

  1. Man schreibt sich also ein Dockerfile mit allen notwendigen apt-get install Anweisungen (oder was auch immer das eingesetzte Linux braucht).
  2. 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 .
  3. Am Ende wird per
    docker push MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG das Image auf DockerHub hochgeladen.
  4. Nun kann bitbucket-pipelines.yml um folgende beiden YAML Einträge erweitert werden:
    1image:
    2  name: MY_DOCKERHUB_USER/MY_IMAGE_NAME:MY_TAG
    

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.